Winsock 커널 애플리케이션 등록
WSK 클라이언트 개체 등록
WSK(Winsock Kernel) 애플리케이션은 WskRegister 함수를 호출하여 WSK 클라이언트로 등록해야 합니다. WskRegister를 사용하려면 WSK 애플리케이션이 WSK 클라이언트의 NPI(네트워크 프로그래밍 인터페이스)(WSK_CLIENT_NPI 구조) 및 WSK 등록 개체(WSK_REGISTRATION 구조)에 대한 포인터를 초기화하고 전달해야 합니다. 이 개체는 성공적으로 반환될 때 WskRegister에서 초기화됩니다.
다음 코드 예제에서는 WSK 애플리케이션이 WSK 클라이언트로 등록할 수 있는 방법을 보여 줍니다.
// Include the WSK header file
#include "wsk.h"
// WSK Client Dispatch table that denotes the WSK version
// that the WSK application wants to use and optionally a pointer
// to the WskClientEvent callback function
const WSK_CLIENT_DISPATCH WskAppDispatch = {
MAKE_WSK_VERSION(1,0), // Use WSK version 1.0
0, // Reserved
NULL // WskClientEvent callback not required for WSK version 1.0
};
// WSK Registration object
WSK_REGISTRATION WskRegistration;
// DriverEntry function
NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status;
WSK_CLIENT_NPI wskClientNpi;
.
.
.
// Register the WSK application
wskClientNpi.ClientContext = NULL;
wskClientNpi.Dispatch = &WskAppDispatch;
Status = WskRegister(&wskClientNpi, &WskRegistration);
if(!NT_SUCCESS(Status)) {
.
.
.
return Status;
}
.
.
.
}
WSK 애플리케이션은 DriverEntry 함수 내에서 WskRegister를 호출할 필요가 없습니다. 예를 들어 WSK 애플리케이션이 복잡한 드라이버의 하위 구성 요소인 경우 WSK 애플리케이션 하위 구성 요소가 활성화된 경우에만 애플리케이션 등록이 발생할 수 있습니다.
WSK 애플리케이션은 WskDeregister가 호출되고 등록이 더 이상 유효하지 않을 때까지 WskRegister에 전달된 WSK_CLIENT_DISPATCH 구조를 유효하고 메모리에 상주해야 합니다. WSK 애플리케이션이 다른 WSK 등록 함수에 대한 호출을 중지할 때까지 WSK_REGISTRATION 구조도 유효하고 메모리에 상주해야 합니다. 이전 코드 예제에서는 드라이버의 전역 데이터 섹션에 이러한 두 구조를 유지하므로 드라이버가 언로드될 때까지 구조체 데이터를 메모리에 유지합니다.
WSK 공급자 NPI 캡처
WSK 애플리케이션이 WskRegister를 사용하여 WSK 클라이언트로 등록한 후 WSK 인터페이스 사용을 시작하려면 WskCaptureProviderNPI 함수를 사용하여 WSK 하위 시스템의 WSK 공급자 NPI를 캡처해야 합니다.
WSK 애플리케이션이 WSK 공급자 NPI를 캡처하려고 할 때 WSK 하위 시스템이 아직 준비되지 않았을 수 있으므로 WskCaptureProviderNPI 함수를 사용하면 WSK 애플리케이션이 다음과 같이 WSK 하위 시스템을 폴링하거나 대기할 수 있습니다.
WaitTimeout 매개 변수가 WSK_NO_WAIT 경우 함수는 항상 기다리지 않고 즉시 반환됩니다.
WaitTimeout이 WSK_INFINITE_WAIT 경우 함수는 WSK 하위 시스템이 준비될 때까지 기다립니다.
WaitTimeout이 다른 값이면 WSK 하위 시스템이 준비될 때 또는 대기 시간(밀리초)이 먼저 발생하는 WaitTimeout 값에 도달할 때 함수가 반환됩니다.
중요 다른 드라이버 및 서비스의 시작에 부정적인 영향을 주지 않도록 하기 위해 DriverEntry 함수에서 WskCaptureProviderNPI를 호출하는 WSK 애플리케이션은 WaitTimeout 매개 변수를 WSK_INFINITE_WAIT 또는 과도한 대기 시간으로 설정해서는 안 됩니다. 또한 WSK 애플리케이션이 시스템 시작 단계에서 매우 일찍 시작되는 경우 WSK 하위 시스템이 DriverEntry 가 실행되는 것과 다른 작업자 스레드에서 준비될 때까지 기다려야 합니다.
WskCaptureProviderNPI에 대한 호출이 STATUS_NOINTERFACE 실패하면 WSK 애플리케이션은 WskQueryProviderCharacteristics 함수를 사용하여 WSK 하위 시스템이 지원하는 WSK NPI 버전의 범위를 검색할 수 있습니다. WSK 애플리케이션은 WskDeregister 를 호출하여 현재 등록 인스턴스의 등록을 취소한 다음 지원되는 WSK NPI 버전을 사용하는 다른 WSK_CLIENT_DISPATCH 인스턴스를 사용하여 다시 등록할 수 있습니다.
WskCaptureProviderNPI가 성공적으로 반환되면 WskProviderNpi 매개 변수는 WSK 애플리케이션에서 사용할 준비가 된 WSK 공급자 NPI(WSK_PROVIDER_NPI)를 가리킵니다. WSK_PROVIDER_NPI 구조에는 WSK 클라이언트 개체( WSK_CLIENT)에 대한 포인터와 WSK 애플리케이션이 WSK 소켓을 만들고 WSK 클라이언트 개체에서 다른 작업을 수행하는 데 사용할 수 있는 WSK 함수의 WSK_PROVIDER_DISPATCH 디스패 치 테이블이 포함됩니다. WSK 애플리케이션이 WSK_PROVIDER_DISPATCH 함수 사용을 완료한 후 WskReleaseProviderNPI를 호출하여 WSK 공급자 NPI를 해제해야 합니다.
다음 코드 예제에서는 WSK 애플리케이션이 WSK 공급자 NPI를 캡처하고 이를 사용하여 소켓을 만든 다음 해제하는 방법을 보여 줍니다.
// WSK application routine that waits for WSK subsystem
// to become ready and captures the WSK Provider NPI
NTSTATUS
WskAppWorkerRoutine(
)
{
NTSTATUS Status;
WSK_PROVIDER_NPI wskProviderNpi;
// Capture the WSK Provider NPI. If WSK subsystem is not ready yet,
// wait until it becomes ready.
Status = WskCaptureProviderNPI(
&WskRegistration, // must have been initialized with WskRegister
WSK_INFINITE_WAIT,
&wskProviderNpi
);
if(!NT_SUCCESS(Status))
{
// The WSK Provider NPI could not be captured.
if( Status == STATUS_NOINTERFACE ) {
// WSK application's requested version is not supported
}
else if( status == STATUS_DEVICE_NOT_READY ) {
// WskDeregister was invoked in another thread thereby causing
// WskCaptureProviderNPI to be canceled.
}
else {
// Some other unexpected failure has occurred
}
return Status;
}
// The WSK Provider NPI has been captured.
// Create and set up a listening socket that accepts
// incoming connections.
Status = CreateListeningSocket(&wskProviderNpi, ...);
// The WSK Provider NPI will not be used any more.
// So, release it here immediately.
WskReleaseProviderNPI(&WskRegistration);
// Return result of socket creation routine
return Status;
}
WSK 애플리케이션은 WskCaptureProviderNPI 를 두 번 이상 호출할 수 있습니다. 성공적으로 반환되는 WskCaptureProviderNPI 호출마다 WskReleaseProviderNPI에 대한 해당 호출이 있어야 합니다. WSK 애플리케이션은 WskReleaseProviderNPI를 호출한 후 WSK_PROVIDER_DISPATCH 함수를 더 이상 호출하지 않아야 합니다.