NotifyAddrChange
関数シグネチャ
// IPHLPAPI.dll
#include <windows.h>
DWORD NotifyAddrChange(
HANDLE* Handle,
OVERLAPPED* overlapped
);パラメーター
| 名前 | 型 | 方向 | 説明 |
|---|---|---|---|
| Handle | HANDLE* | out | 後続の GetOverlappedResult 関数の呼び出しで使用するファイルハンドルを受け取る HANDLE 変数へのポインターです。 警告 このハンドルをクローズしないでください。また、完了ポートに関連付けないでください。
|
| overlapped | OVERLAPPED* | in | IP アドレスとインターフェイスを対応付けるテーブルに変更があった場合に呼び出し元へ通知する OVERLAPPED 構造体へのポインターです。 |
戻り値の型: DWORD
公式ドキュメント
NotifyAddrChange 関数は、IPv4 アドレスとインターフェイスを対応付けるテーブルに変更が発生するたびに、呼び出し元へ通知を送信します。
戻り値
関数が成功した場合、Handle および overlapped パラメーターに NULL を指定したときの戻り値は NO_ERROR です。呼び出し元が NULL 以外のパラメーターを指定した場合、成功時の戻り値は ERROR_IO_PENDING です。
関数が失敗した場合は、 FormatMessage を使用して、返されたエラーに対応するメッセージ文字列を取得してください。
| 戻り値 | 説明 |
|---|---|
| コンテキストの登録解除が行われているため、呼び出しは即座にキャンセルされました。 | |
| 無効なパラメーターが渡されました。このエラーは、Handle と overlapped の両方のパラメーターが NULL ではないものの、入力パラメーターで指定されたメモリに呼び出し元プロセスが書き込めない場合に返されます。また、クライアントが既に変更通知要求を行っている場合にも、この重複した要求は失敗し、このエラーが返されます。 | |
| 操作を完了するのに十分なメモリがありませんでした。 | |
| このエラーは、Windows 98/95 や Windows NT 4.0 など、この関数がサポートされていないバージョンの Windows で返されます。 |
解説(Remarks)
NotifyAddrChange 関数は、次の 2 つの方法で呼び出すことができます。
- 同期方式
- 非同期方式
呼び出し元が Handle および overlapped パラメーターに NULL を指定した場合、 NotifyAddrChange の呼び出しは同期的になり、IP アドレスの変更が発生するまでブロックします。この場合、変更が発生すると NotifyAddrChange 関数が完了し、変更が発生したことを示します。
NotifyAddrChange 関数を同期的に呼び出した場合、アプリケーションが終了するまで、次の IPv4 アドレス変更時に通知が送信されます。
呼び出し元がハンドル変数と OVERLAPPED 構造体を指定した場合、NotifyAddrChange 関数の呼び出しは非同期的になり、呼び出し元は返されたハンドルと OVERLAPPED 構造体を使用して、GetOverlappedResult 関数により IPv4 アドレス変更の非同期通知を受け取ることができます。ハンドルと OVERLAPPED 構造体を使用して通知を受け取る方法については、次のトピックを参照してください。
CancelIPChangeNotify 関数は、NotifyAddrChange または NotifyRouteChange 関数の呼び出しに成功して要求していた IPv4 アドレスおよびルートの変更通知をキャンセルします。アプリケーションは変更の通知を受け取った後、GetIpAddrTable または GetAdaptersAddresses 関数を呼び出して IPv4 アドレスのテーブルを取得し、何が変更されたかを判断できます。アプリケーションが通知を受け取り、次の変更についても通知が必要な場合は、NotifyAddrChange 関数を再度呼び出す必要があります。
NotifyAddrChange 関数を非同期的に呼び出した場合、アプリケーションが CancelIPChangeNotify 関数を呼び出して通知をキャンセルするか、またはアプリケーションが終了するまで、次の IPv4 アドレス変更時に通知が送信されます。アプリケーションが終了すると、システムは通知の登録を自動的にキャンセルします。ただし、アプリケーションは終了前にすべての通知を明示的にキャンセルすることが推奨されます。
通知の登録は、システムのシャットダウンや再起動をまたいで保持されることはありません。
Windows Vista 以降では、 NotifyIpInterfaceChange 関数を使用して、ローカルコンピューター上の IPv4 および IPv6 インターフェイスの変更通知を登録できます。
使用例
次の例では、IP アドレスとインターフェイスを対応付けるテーブルに変更が発生するのを待機します。
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
void main()
{
OVERLAPPED overlap;
DWORD ret;
HANDLE hand = NULL;
overlap.hEvent = WSACreateEvent();
ret = NotifyAddrChange(&hand, &overlap);
if (ret != NO_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("NotifyAddrChange error...%d\n", WSAGetLastError());
return;
}
}
if ( WaitForSingleObject(overlap.hEvent, INFINITE) == WAIT_OBJECT_0 )
printf("IP Address table changed..\n");
}
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での呼び出し定義
// IPHLPAPI.dll
#include <windows.h>
DWORD NotifyAddrChange(
HANDLE* Handle,
OVERLAPPED* overlapped
);[DllImport("IPHLPAPI.dll", ExactSpelling = true)]
static extern uint NotifyAddrChange(
IntPtr Handle, // HANDLE* out
IntPtr overlapped // OVERLAPPED*
);<DllImport("IPHLPAPI.dll", ExactSpelling:=True)>
Public Shared Function NotifyAddrChange(
Handle As IntPtr, ' HANDLE* out
overlapped As IntPtr ' OVERLAPPED*
) As UInteger
End Function' Handle : HANDLE* out
' overlapped : OVERLAPPED*
Declare PtrSafe Function NotifyAddrChange Lib "iphlpapi" ( _
ByVal Handle As LongPtr, _
ByVal overlapped As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。import ctypes
from ctypes import wintypes
NotifyAddrChange = ctypes.windll.iphlpapi.NotifyAddrChange
NotifyAddrChange.restype = wintypes.DWORD
NotifyAddrChange.argtypes = [
ctypes.c_void_p, # Handle : HANDLE* out
ctypes.c_void_p, # overlapped : OVERLAPPED*
]require 'fiddle'
require 'fiddle/import'
lib = Fiddle.dlopen('IPHLPAPI.dll')
NotifyAddrChange = Fiddle::Function.new(
lib['NotifyAddrChange'],
[
Fiddle::TYPE_VOIDP, # Handle : HANDLE* out
Fiddle::TYPE_VOIDP, # overlapped : OVERLAPPED*
],
-Fiddle::TYPE_INT)#[link(name = "iphlpapi")]
extern "system" {
fn NotifyAddrChange(
Handle: *mut *mut core::ffi::c_void, // HANDLE* out
overlapped: *mut OVERLAPPED // OVERLAPPED*
) -> u32;
}
// crates: windows-sys provides ready-made bindings for this API.$sig = @"
[DllImport("IPHLPAPI.dll")]
public static extern uint NotifyAddrChange(IntPtr Handle, IntPtr overlapped);
"@
$api = Add-Type -MemberDefinition $sig -Name 'IPHLPAPI_NotifyAddrChange' -Namespace Win32 -PassThru
# $api::NotifyAddrChange(Handle, overlapped)#uselib "IPHLPAPI.dll"
#func global NotifyAddrChange "NotifyAddrChange" sptr, sptr
; NotifyAddrChange Handle, varptr(overlapped) ; 戻り値は stat
; Handle : HANDLE* out -> "sptr"
; overlapped : OVERLAPPED* -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。#uselib "IPHLPAPI.dll" #cfunc global NotifyAddrChange "NotifyAddrChange" sptr, var ; res = NotifyAddrChange(Handle, overlapped) ; Handle : HANDLE* out -> "sptr" ; overlapped : OVERLAPPED* -> "var" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。#uselib "IPHLPAPI.dll" #cfunc global NotifyAddrChange "NotifyAddrChange" sptr, sptr ; res = NotifyAddrChange(Handle, varptr(overlapped)) ; Handle : HANDLE* out -> "sptr" ; overlapped : OVERLAPPED* -> "sptr" ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。
; DWORD NotifyAddrChange(HANDLE* Handle, OVERLAPPED* overlapped) #uselib "IPHLPAPI.dll" #cfunc global NotifyAddrChange "NotifyAddrChange" intptr, var ; res = NotifyAddrChange(Handle, overlapped) ; Handle : HANDLE* out -> "intptr" ; overlapped : OVERLAPPED* -> "var" ; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。; DWORD NotifyAddrChange(HANDLE* Handle, OVERLAPPED* overlapped) #uselib "IPHLPAPI.dll" #cfunc global NotifyAddrChange "NotifyAddrChange" intptr, intptr ; res = NotifyAddrChange(Handle, varptr(overlapped)) ; Handle : HANDLE* out -> "intptr" ; overlapped : OVERLAPPED* -> "intptr" ; ※出力/バッファ引数はポインタ方式(token=intptr / 呼び出しは varptr(変数))。
import (
"golang.org/x/sys/windows"
"unsafe"
)
var (
iphlpapi = windows.NewLazySystemDLL("IPHLPAPI.dll")
procNotifyAddrChange = iphlpapi.NewProc("NotifyAddrChange")
)
// Handle (HANDLE* out), overlapped (OVERLAPPED*)
r1, _, err := procNotifyAddrChange.Call(
uintptr(Handle),
uintptr(overlapped),
)
_ = err // syscall.Errno (valid when the call sets last-error)
_ = r1 // DWORDfunction NotifyAddrChange(
Handle: Pointer; // HANDLE* out
overlapped: Pointer // OVERLAPPED*
): DWORD; stdcall;
external 'IPHLPAPI.dll' name 'NotifyAddrChange';result := DllCall("IPHLPAPI\NotifyAddrChange"
, "Ptr", Handle ; HANDLE* out
, "Ptr", overlapped ; OVERLAPPED*
, "UInt") ; return: DWORD●NotifyAddrChange(Handle, overlapped) = DLL("IPHLPAPI.dll", "dword NotifyAddrChange(void*, void*)")
# 呼び出し: NotifyAddrChange(Handle, overlapped)
# Handle : HANDLE* out -> "void*"
# overlapped : OVERLAPPED* -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。const std = @import("std");
extern "iphlpapi" fn NotifyAddrChange(
Handle: ?*anyopaque, // HANDLE* out
overlapped: [*c]OVERLAPPED // OVERLAPPED*
) callconv(std.os.windows.WINAPI) u32;proc NotifyAddrChange(
Handle: pointer, # HANDLE* out
overlapped: ptr OVERLAPPED # OVERLAPPED*
): uint32 {.importc: "NotifyAddrChange", stdcall, dynlib: "IPHLPAPI.dll".}pragma(lib, "iphlpapi");
extern(Windows)
uint NotifyAddrChange(
void* Handle, // HANDLE* out
OVERLAPPED* overlapped // OVERLAPPED*
);ccall((:NotifyAddrChange, "IPHLPAPI.dll"), stdcall, UInt32,
(Ptr{Cvoid}, Ptr{OVERLAPPED}),
Handle, overlapped)
# Handle : HANDLE* out -> Ptr{Cvoid}
# overlapped : OVERLAPPED* -> Ptr{OVERLAPPED}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。local ffi = require("ffi")
ffi.cdef[[
uint32_t NotifyAddrChange(
void* Handle,
void* overlapped);
]]
local iphlpapi = ffi.load("iphlpapi")
-- iphlpapi.NotifyAddrChange(Handle, overlapped)
-- Handle : HANDLE* out
-- overlapped : OVERLAPPED*
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。const koffi = require('koffi');
const lib = koffi.load('IPHLPAPI.dll');
const NotifyAddrChange = lib.func('__stdcall', 'NotifyAddrChange', 'uint32_t', ['void *', 'void *']);
// NotifyAddrChange(Handle, overlapped)
// Handle : HANDLE* out -> 'void *'
// overlapped : OVERLAPPED* -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。const lib = Deno.dlopen("IPHLPAPI.dll", {
NotifyAddrChange: { parameters: ["pointer", "pointer"], result: "u32" },
});
// lib.symbols.NotifyAddrChange(Handle, overlapped)
// Handle : HANDLE* out -> "pointer"
// overlapped : OVERLAPPED* -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。<?php
$ffi = FFI::cdef(<<<C
uint32_t NotifyAddrChange(
void* Handle,
void* overlapped);
C, "IPHLPAPI.dll");
// $ffi->NotifyAddrChange(Handle, overlapped);
// Handle : HANDLE* out
// overlapped : OVERLAPPED*
// 構造体/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 Iphlpapi extends StdCallLibrary {
Iphlpapi INSTANCE = Native.load("iphlpapi", Iphlpapi.class);
int NotifyAddrChange(
Pointer Handle, // HANDLE* out
Pointer overlapped // OVERLAPPED*
);
}@[Link("iphlpapi")]
lib LibIPHLPAPI
fun NotifyAddrChange = NotifyAddrChange(
Handle : Void*, # HANDLE* out
overlapped : OVERLAPPED* # OVERLAPPED*
) : UInt32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef NotifyAddrChangeNative = Uint32 Function(Pointer<Void>, Pointer<Void>);
typedef NotifyAddrChangeDart = int Function(Pointer<Void>, Pointer<Void>);
final NotifyAddrChange = DynamicLibrary.open('IPHLPAPI.dll')
.lookupFunction<NotifyAddrChangeNative, NotifyAddrChangeDart>('NotifyAddrChange');
// Handle : HANDLE* out -> Pointer<Void>
// overlapped : OVERLAPPED* -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。{$mode objfpc}{$H+}
function NotifyAddrChange(
Handle: Pointer; // HANDLE* out
overlapped: Pointer // OVERLAPPED*
): DWORD; stdcall;
external 'IPHLPAPI.dll' name 'NotifyAddrChange';import Foreign
import Foreign.C.Types
import Foreign.C.String
foreign import stdcall safe "NotifyAddrChange"
c_NotifyAddrChange :: Ptr () -> Ptr () -> IO Word32
-- Handle : HANDLE* out -> Ptr ()
-- overlapped : OVERLAPPED* -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。open Ctypes
open Foreign
let notifyaddrchange =
foreign "NotifyAddrChange"
((ptr void) @-> (ptr void) @-> returning uint32_t)
(* Handle : HANDLE* out -> (ptr void) *)
(* overlapped : OVERLAPPED* -> (ptr void) *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)(cffi:define-foreign-library iphlpapi (t "IPHLPAPI.dll"))
(cffi:use-foreign-library iphlpapi)
(cffi:defcfun ("NotifyAddrChange" notify-addr-change :convention :stdcall) :uint32
(handle :pointer) ; HANDLE* out
(overlapped :pointer)) ; OVERLAPPED*
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。use Win32::API;
my $NotifyAddrChange = Win32::API::More->new('IPHLPAPI',
'DWORD NotifyAddrChange(HANDLE Handle, LPVOID overlapped)');
# my $ret = $NotifyAddrChange->Call($Handle, $overlapped);
# Handle : HANDLE* out -> HANDLE
# overlapped : OVERLAPPED* -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。関連項目
- f CancelIPChangeNotify — IPアドレスや経路変更の通知登録を解除する。
- f GetAdaptersAddresses — アダプターのIPアドレス等の詳細情報を取得する。
- f GetIpAddrTable — 各インターフェイスに割り当てられたIPv4アドレスの一覧表を取得する。
- f GetOverlappedResult — オーバーラップI/O操作の結果を取得する。
- f NotifyIpInterfaceChange — IPインターフェイスの変更を通知するコールバックを登録する。
- f NotifyRouteChange — ルーティングテーブルの変更を通知するよう登録する。