Почему этот вызов WSAIoctl для загрузки AcceptEx возвращает 10022?

Я пытаюсь загрузить указатель на функцию AcceptEx для кода, преобразованного из примера Microsoft IOCPSERVEREX.CPP, который по сути совпадает с примером кода на странице microsoft.com AcceptEx(). Я использую Delphi 6, отсюда и встроенные определения Winsock2. Я сократил все до этого небольшого примера, но WSAIoctl всегда возвращает ошибку 10022, и я не могу понять, почему.

program test;

{$APPTYPE CONSOLE}

uses windows, winsock;

type
  GUID = packed record
    D1: DWORD;
    D2: DWORD;
    D3: DWORD;
    D4: array[0..7] of BYTE;
    end;

  PAddrInfo = ^addrinfo;
  addrinfo = packed record
    ai_flags, ai_family, ai_socktype, ai_protocol: integer;
    ai_addrlen: Cardinal;
    ai_canonname: PAnsiChar;
    ai_addr: PSockAddrIn;
    ai_next: PAddrInfo;
    end;

const
  AI_PASSIVE = $01;
  IOC_WS2 = $08000000;
  IOC_OUT = $40000000;
  IOC_IN = $80000000;
  IOC_INOUT = (IOC_IN or IOC_OUT);
  SIO_GET_EXTENSION_FUNCTION_POINTER = 6 or IOC_WS2 or IOC_INOUT;
  WSA_FLAG_OVERLAPPED = $01;
  WSAID_ACCEPTEX: GUID = (D1:$b5367df1; D2:$cbac; D3:$11cf; D4:($95, $ca, $00, $80, $5f, $48, $a1, $92)); // GUID to Microsoft specific extensions

function GetAddrInfo(nodename, servname: PAnsiChar; pHints: PAddrInfo; out res: PAddrInfo): integer; stdcall; external 'ws2_32.dll' name 'getaddrinfo';
function WSAIoctl(const s: TSocket; dwIoControlCode: DWORD; lpvInBuffer: Pointer; cbInBuffer: DWORD; lpvOutBuffer: Pointer; cbOutBuffer: DWORD;
  lpcbBytesReturned: LPDWORD; AOverlapped: Pointer; lpCompletionRoutine: pointer): LongInt; stdcall; external 'ws2_32.dll' name 'WSAIoctl';
function WSASocketA(af, iType, protocol: Integer; lpProtocolInfo: pointer; grp, dwFlags: DWORD): TSocket; stdcall; external 'ws2_32.dll' name 'WSASocketA';

var
  wsaData: TWSADATA;
  g_hIOCP: THANDLE;
  hints: addrinfo;
  g_sdListen: TSOCKET;
  addrlocal: PAddrInfo;
  P: pointer; Bytes: dword;

begin
if WSAStartup(MAKEWORD(2,2), wsaData) <> 0 then writeln('WSAStartup failed');
g_hIOCP := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
if g_hIOCP = 0 then writeln('CreateIoCompletionPort failed');
fillchar(hints, sizeof(hints), 0);
hints.ai_flags  := AI_PASSIVE;
hints.ai_family := AF_INET;
hints.ai_socktype := SOCK_STREAM;
hints.ai_protocol := IPPROTO_IP;
if getaddrinfo('localhost', '80', PAddrInfo(@hints), addrlocal) <> 0  then writeln('getaddrinfo failed');
if addrlocal = nil then writeln('no addrlocal');
g_sdListen := WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_IP, nil, 0, WSA_FLAG_OVERLAPPED);
if g_sdListen = INVALID_SOCKET then writeln('WSASocketA failed');
if bind(g_sdListen, addrlocal^.ai_addr^, integer(addrlocal^.ai_addrlen)) = SOCKET_ERROR then writeln('bind failed');
if listen(g_sdListen, 5) = SOCKET_ERROR then writeln('listen failed');
g_hIOCP := CreateIoCompletionPort(THANDLE(g_sdListen), g_hIOCP, 0, 0);
if g_hIOCP = 0 then writeln('CreateIoCompletionPort failed');
if WSAIoctl(g_sdListen, SIO_GET_EXTENSION_FUNCTION_POINTER, @WSAID_ACCEPTEX, sizeof(WSAID_ACCEPTEX), @P, SizeOf(P), @Bytes, nil, nil) = SOCKET_ERROR then
  writeln('AcceptEx failed to load: ', WSAGetLastError);
write('exit:'); readln;
end.

0 ответов

Другие вопросы по тегам