PageRenderTime 78ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/dll/win32/msafd/misc/dllmain.c

https://bitbucket.org/arty/arty-newcc-reactos
C | 3025 lines | 2301 code | 424 blank | 300 comment | 367 complexity | 0e9108fd373225420c56433e6347f8f6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-3.0, CC-BY-SA-3.0, AGPL-3.0, GPL-3.0, CPL-1.0
  1. /*
  2. * COPYRIGHT: See COPYING in the top level directory
  3. * PROJECT: ReactOS Ancillary Function Driver DLL
  4. * FILE: misc/dllmain.c
  5. * PURPOSE: DLL entry point
  6. * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
  7. * Alex Ionescu (alex@relsoft.net)
  8. * REVISIONS:
  9. * CSH 01/09-2000 Created
  10. * Alex 16/07/2004 - Complete Rewrite
  11. */
  12. #include <msafd.h>
  13. #if DBG
  14. //DWORD DebugTraceLevel = DEBUG_ULTRA;
  15. DWORD DebugTraceLevel = 0;
  16. #endif /* DBG */
  17. HANDLE GlobalHeap;
  18. WSPUPCALLTABLE Upcalls;
  19. LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
  20. PSOCKET_INFORMATION SocketListHead = NULL;
  21. CRITICAL_SECTION SocketListLock;
  22. LIST_ENTRY SockHelpersListHead = { NULL, NULL };
  23. ULONG SockAsyncThreadRefCount;
  24. HANDLE SockAsyncHelperAfdHandle;
  25. HANDLE SockAsyncCompletionPort = NULL;
  26. BOOLEAN SockAsyncSelectCalled;
  27. /*
  28. * FUNCTION: Creates a new socket
  29. * ARGUMENTS:
  30. * af = Address family
  31. * type = Socket type
  32. * protocol = Protocol type
  33. * lpProtocolInfo = Pointer to protocol information
  34. * g = Reserved
  35. * dwFlags = Socket flags
  36. * lpErrno = Address of buffer for error information
  37. * RETURNS:
  38. * Created socket, or INVALID_SOCKET if it could not be created
  39. */
  40. SOCKET
  41. WSPAPI
  42. WSPSocket(int AddressFamily,
  43. int SocketType,
  44. int Protocol,
  45. LPWSAPROTOCOL_INFOW lpProtocolInfo,
  46. GROUP g,
  47. DWORD dwFlags,
  48. LPINT lpErrno)
  49. {
  50. OBJECT_ATTRIBUTES Object;
  51. IO_STATUS_BLOCK IOSB;
  52. USHORT SizeOfPacket;
  53. ULONG SizeOfEA;
  54. PAFD_CREATE_PACKET AfdPacket;
  55. HANDLE Sock;
  56. PSOCKET_INFORMATION Socket = NULL;
  57. PFILE_FULL_EA_INFORMATION EABuffer = NULL;
  58. PHELPER_DATA HelperData;
  59. PVOID HelperDLLContext;
  60. DWORD HelperEvents;
  61. UNICODE_STRING TransportName;
  62. UNICODE_STRING DevName;
  63. LARGE_INTEGER GroupData;
  64. INT Status;
  65. AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n"));
  66. AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d) SocketType (%d) Protocol (%d).\n",
  67. AddressFamily, SocketType, Protocol));
  68. /* Get Helper Data and Transport */
  69. Status = SockGetTdiName (&AddressFamily,
  70. &SocketType,
  71. &Protocol,
  72. g,
  73. dwFlags,
  74. &TransportName,
  75. &HelperDLLContext,
  76. &HelperData,
  77. &HelperEvents);
  78. /* Check for error */
  79. if (Status != NO_ERROR)
  80. {
  81. AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status));
  82. goto error;
  83. }
  84. /* AFD Device Name */
  85. RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
  86. /* Set Socket Data */
  87. Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
  88. if (!Socket)
  89. return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
  90. RtlZeroMemory(Socket, sizeof(*Socket));
  91. Socket->RefCount = 2;
  92. Socket->Handle = -1;
  93. Socket->SharedData.Listening = FALSE;
  94. Socket->SharedData.State = SocketOpen;
  95. Socket->SharedData.AddressFamily = AddressFamily;
  96. Socket->SharedData.SocketType = SocketType;
  97. Socket->SharedData.Protocol = Protocol;
  98. Socket->HelperContext = HelperDLLContext;
  99. Socket->HelperData = HelperData;
  100. Socket->HelperEvents = HelperEvents;
  101. Socket->LocalAddress = &Socket->WSLocalAddress;
  102. Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
  103. Socket->RemoteAddress = &Socket->WSRemoteAddress;
  104. Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
  105. Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
  106. Socket->SharedData.CreateFlags = dwFlags;
  107. Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
  108. Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1;
  109. Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags;
  110. Socket->SharedData.GroupID = g;
  111. Socket->SharedData.GroupType = 0;
  112. Socket->SharedData.UseSAN = FALSE;
  113. Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */
  114. Socket->SanData = NULL;
  115. /* Ask alex about this */
  116. if( Socket->SharedData.SocketType == SOCK_DGRAM ||
  117. Socket->SharedData.SocketType == SOCK_RAW )
  118. {
  119. AFD_DbgPrint(MID_TRACE,("Connectionless socket\n"));
  120. Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS;
  121. }
  122. /* Packet Size */
  123. SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);
  124. /* EA Size */
  125. SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH;
  126. /* Set up EA Buffer */
  127. EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
  128. if (!EABuffer)
  129. return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
  130. RtlZeroMemory(EABuffer, SizeOfEA);
  131. EABuffer->NextEntryOffset = 0;
  132. EABuffer->Flags = 0;
  133. EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
  134. RtlCopyMemory (EABuffer->EaName,
  135. AfdCommand,
  136. AFD_PACKET_COMMAND_LENGTH + 1);
  137. EABuffer->EaValueLength = SizeOfPacket;
  138. /* Set up AFD Packet */
  139. AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
  140. AfdPacket->SizeOfTransportName = TransportName.Length;
  141. RtlCopyMemory (AfdPacket->TransportName,
  142. TransportName.Buffer,
  143. TransportName.Length + sizeof(WCHAR));
  144. AfdPacket->GroupID = g;
  145. /* Set up Endpoint Flags */
  146. if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0)
  147. {
  148. if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW))
  149. {
  150. /* Only RAW or UDP can be Connectionless */
  151. goto error;
  152. }
  153. AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
  154. }
  155. if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0)
  156. {
  157. if (SocketType == SOCK_STREAM)
  158. {
  159. if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0)
  160. {
  161. /* The Provider doesn't actually support Message Oriented Streams */
  162. goto error;
  163. }
  164. }
  165. AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
  166. }
  167. if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
  168. if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT |
  169. WSA_FLAG_MULTIPOINT_C_LEAF |
  170. WSA_FLAG_MULTIPOINT_D_ROOT |
  171. WSA_FLAG_MULTIPOINT_D_LEAF))
  172. {
  173. if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0)
  174. {
  175. /* The Provider doesn't actually support Multipoint */
  176. goto error;
  177. }
  178. AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
  179. if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT)
  180. {
  181. if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0)
  182. || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0))
  183. {
  184. /* The Provider doesn't support Control Planes, or you already gave a leaf */
  185. goto error;
  186. }
  187. AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
  188. }
  189. if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT)
  190. {
  191. if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0)
  192. || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0))
  193. {
  194. /* The Provider doesn't support Data Planes, or you already gave a leaf */
  195. goto error;
  196. }
  197. AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
  198. }
  199. }
  200. /* Set up Object Attributes */
  201. InitializeObjectAttributes (&Object,
  202. &DevName,
  203. OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
  204. 0,
  205. 0);
  206. /* Create the Socket as asynchronous. That means we have to block
  207. ourselves after every call to NtDeviceIoControlFile. This is
  208. because the kernel doesn't support overlapping synchronous I/O
  209. requests (made from multiple threads) at this time (Sep 2005) */
  210. Status = NtCreateFile(&Sock,
  211. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  212. &Object,
  213. &IOSB,
  214. NULL,
  215. 0,
  216. FILE_SHARE_READ | FILE_SHARE_WRITE,
  217. FILE_OPEN_IF,
  218. 0,
  219. EABuffer,
  220. SizeOfEA);
  221. HeapFree(GlobalHeap, 0, EABuffer);
  222. if (Status != STATUS_SUCCESS)
  223. {
  224. AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n"));
  225. HeapFree(GlobalHeap, 0, Socket);
  226. return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
  227. }
  228. /* Save Handle */
  229. Socket->Handle = (SOCKET)Sock;
  230. /* Save Group Info */
  231. if (g != 0)
  232. {
  233. GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
  234. Socket->SharedData.GroupID = GroupData.u.LowPart;
  235. Socket->SharedData.GroupType = GroupData.u.HighPart;
  236. }
  237. /* Get Window Sizes and Save them */
  238. GetSocketInformation (Socket,
  239. AFD_INFO_SEND_WINDOW_SIZE,
  240. NULL,
  241. &Socket->SharedData.SizeOfSendBuffer,
  242. NULL);
  243. GetSocketInformation (Socket,
  244. AFD_INFO_RECEIVE_WINDOW_SIZE,
  245. NULL,
  246. &Socket->SharedData.SizeOfRecvBuffer,
  247. NULL);
  248. /* Save in Process Sockets List */
  249. EnterCriticalSection(&SocketListLock);
  250. Socket->NextSocket = SocketListHead;
  251. SocketListHead = Socket;
  252. LeaveCriticalSection(&SocketListLock);
  253. /* Create the Socket Context */
  254. CreateContext(Socket);
  255. /* Notify Winsock */
  256. Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno);
  257. /* Return Socket Handle */
  258. AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock));
  259. return (SOCKET)Sock;
  260. error:
  261. AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status));
  262. if( Socket )
  263. HeapFree(GlobalHeap, 0, Socket);
  264. if( lpErrno )
  265. *lpErrno = Status;
  266. return INVALID_SOCKET;
  267. }
  268. INT
  269. TranslateNtStatusError(NTSTATUS Status)
  270. {
  271. switch (Status)
  272. {
  273. case STATUS_CANT_WAIT:
  274. return WSAEWOULDBLOCK;
  275. case STATUS_TIMEOUT:
  276. return WSAETIMEDOUT;
  277. case STATUS_SUCCESS:
  278. return NO_ERROR;
  279. case STATUS_FILE_CLOSED:
  280. case STATUS_END_OF_FILE:
  281. return WSAESHUTDOWN;
  282. case STATUS_PENDING:
  283. return WSA_IO_PENDING;
  284. case STATUS_BUFFER_TOO_SMALL:
  285. case STATUS_BUFFER_OVERFLOW:
  286. DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
  287. return WSAEMSGSIZE;
  288. case STATUS_NO_MEMORY:
  289. case STATUS_INSUFFICIENT_RESOURCES:
  290. DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
  291. return WSAENOBUFS;
  292. case STATUS_INVALID_CONNECTION:
  293. DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
  294. return WSAEAFNOSUPPORT;
  295. case STATUS_INVALID_ADDRESS:
  296. DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n");
  297. return WSAEADDRNOTAVAIL;
  298. case STATUS_REMOTE_NOT_LISTENING:
  299. DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
  300. return WSAECONNREFUSED;
  301. case STATUS_NETWORK_UNREACHABLE:
  302. DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n");
  303. return WSAENETUNREACH;
  304. case STATUS_INVALID_PARAMETER:
  305. DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
  306. return WSAEINVAL;
  307. case STATUS_CANCELLED:
  308. DbgPrint("MSAFD: STATUS_CANCELLED\n");
  309. return WSA_OPERATION_ABORTED;
  310. case STATUS_ADDRESS_ALREADY_EXISTS:
  311. DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n");
  312. return WSAEADDRINUSE;
  313. case STATUS_LOCAL_DISCONNECT:
  314. DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n");
  315. return WSAECONNABORTED;
  316. case STATUS_REMOTE_DISCONNECT:
  317. DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n");
  318. return WSAECONNRESET;
  319. default:
  320. DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status);
  321. return WSAENETDOWN;
  322. }
  323. }
  324. /*
  325. * FUNCTION: Closes an open socket
  326. * ARGUMENTS:
  327. * s = Socket descriptor
  328. * lpErrno = Address of buffer for error information
  329. * RETURNS:
  330. * NO_ERROR, or SOCKET_ERROR if the socket could not be closed
  331. */
  332. INT
  333. WSPAPI
  334. WSPCloseSocket(IN SOCKET Handle,
  335. OUT LPINT lpErrno)
  336. {
  337. IO_STATUS_BLOCK IoStatusBlock;
  338. PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
  339. NTSTATUS Status;
  340. HANDLE SockEvent;
  341. AFD_DISCONNECT_INFO DisconnectInfo;
  342. SOCKET_STATE OldState;
  343. LONG LingerWait = -1;
  344. /* Create the Wait Event */
  345. Status = NtCreateEvent(&SockEvent,
  346. GENERIC_READ | GENERIC_WRITE,
  347. NULL,
  348. 1,
  349. FALSE);
  350. if(!NT_SUCCESS(Status))
  351. return SOCKET_ERROR;
  352. /* Get the Socket Structure associate to this Socket*/
  353. Socket = GetSocketStructure(Handle);
  354. if (!Socket)
  355. {
  356. NtClose(SockEvent);
  357. *lpErrno = WSAENOTSOCK;
  358. return SOCKET_ERROR;
  359. }
  360. if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
  361. {
  362. Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
  363. Socket->Handle,
  364. Socket->TdiAddressHandle,
  365. Socket->TdiConnectionHandle,
  366. WSH_NOTIFY_CLOSE);
  367. if (Status)
  368. {
  369. if (lpErrno) *lpErrno = Status;
  370. NtClose(SockEvent);
  371. return SOCKET_ERROR;
  372. }
  373. }
  374. /* If a Close is already in Process, give up */
  375. if (Socket->SharedData.State == SocketClosed)
  376. {
  377. NtClose(SockEvent);
  378. *lpErrno = WSAENOTSOCK;
  379. return SOCKET_ERROR;
  380. }
  381. /* Set the state to close */
  382. OldState = Socket->SharedData.State;
  383. Socket->SharedData.State = SocketClosed;
  384. /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
  385. /* FIXME: Should we do this on Datagram Sockets too? */
  386. if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
  387. {
  388. ULONG SendsInProgress;
  389. ULONG SleepWait;
  390. /* We need to respect the timeout */
  391. SleepWait = 100;
  392. LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
  393. /* Loop until no more sends are pending, within the timeout */
  394. while (LingerWait)
  395. {
  396. /* Find out how many Sends are in Progress */
  397. if (GetSocketInformation(Socket,
  398. AFD_INFO_SENDS_IN_PROGRESS,
  399. NULL,
  400. &SendsInProgress,
  401. NULL))
  402. {
  403. /* Bail out if anything but NO_ERROR */
  404. LingerWait = 0;
  405. break;
  406. }
  407. /* Bail out if no more sends are pending */
  408. if (!SendsInProgress)
  409. {
  410. LingerWait = -1;
  411. break;
  412. }
  413. /*
  414. * We have to execute a sleep, so it's kind of like
  415. * a block. If the socket is Nonblock, we cannot
  416. * go on since asyncronous operation is expected
  417. * and we cannot offer it
  418. */
  419. if (Socket->SharedData.NonBlocking)
  420. {
  421. NtClose(SockEvent);
  422. Socket->SharedData.State = OldState;
  423. *lpErrno = WSAEWOULDBLOCK;
  424. return SOCKET_ERROR;
  425. }
  426. /* Now we can sleep, and decrement the linger wait */
  427. /*
  428. * FIXME: It seems Windows does some funky acceleration
  429. * since the waiting seems to be longer and longer. I
  430. * don't think this improves performance so much, so we
  431. * wait a fixed time instead.
  432. */
  433. Sleep(SleepWait);
  434. LingerWait -= SleepWait;
  435. }
  436. }
  437. if (OldState == SocketConnected)
  438. {
  439. if (LingerWait <= 0)
  440. {
  441. DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
  442. DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
  443. if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) ||
  444. ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown)))
  445. {
  446. /* Send IOCTL */
  447. Status = NtDeviceIoControlFile((HANDLE)Handle,
  448. SockEvent,
  449. NULL,
  450. NULL,
  451. &IoStatusBlock,
  452. IOCTL_AFD_DISCONNECT,
  453. &DisconnectInfo,
  454. sizeof(DisconnectInfo),
  455. NULL,
  456. 0);
  457. /* Wait for return */
  458. if (Status == STATUS_PENDING)
  459. {
  460. WaitForSingleObject(SockEvent, INFINITE);
  461. Status = IoStatusBlock.Status;
  462. }
  463. }
  464. }
  465. }
  466. /* Cleanup Time! */
  467. Socket->HelperContext = NULL;
  468. Socket->SharedData.AsyncDisabledEvents = -1;
  469. NtClose(Socket->TdiAddressHandle);
  470. Socket->TdiAddressHandle = NULL;
  471. NtClose(Socket->TdiConnectionHandle);
  472. Socket->TdiConnectionHandle = NULL;
  473. EnterCriticalSection(&SocketListLock);
  474. if (SocketListHead == Socket)
  475. {
  476. SocketListHead = SocketListHead->NextSocket;
  477. }
  478. else
  479. {
  480. CurrentSocket = SocketListHead;
  481. while (CurrentSocket->NextSocket)
  482. {
  483. if (CurrentSocket->NextSocket == Socket)
  484. {
  485. CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket;
  486. break;
  487. }
  488. CurrentSocket = CurrentSocket->NextSocket;
  489. }
  490. }
  491. LeaveCriticalSection(&SocketListLock);
  492. /* Close the handle */
  493. NtClose((HANDLE)Handle);
  494. NtClose(SockEvent);
  495. HeapFree(GlobalHeap, 0, Socket);
  496. return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
  497. }
  498. /*
  499. * FUNCTION: Associates a local address with a socket
  500. * ARGUMENTS:
  501. * s = Socket descriptor
  502. * name = Pointer to local address
  503. * namelen = Length of name
  504. * lpErrno = Address of buffer for error information
  505. * RETURNS:
  506. * 0, or SOCKET_ERROR if the socket could not be bound
  507. */
  508. INT
  509. WSPAPI
  510. WSPBind(SOCKET Handle,
  511. const struct sockaddr *SocketAddress,
  512. int SocketAddressLength,
  513. LPINT lpErrno)
  514. {
  515. IO_STATUS_BLOCK IOSB;
  516. PAFD_BIND_DATA BindData;
  517. PSOCKET_INFORMATION Socket = NULL;
  518. NTSTATUS Status;
  519. SOCKADDR_INFO SocketInfo;
  520. HANDLE SockEvent;
  521. /* See below */
  522. BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength);
  523. if (!BindData)
  524. {
  525. return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
  526. }
  527. Status = NtCreateEvent(&SockEvent,
  528. GENERIC_READ | GENERIC_WRITE,
  529. NULL,
  530. 1,
  531. FALSE);
  532. if (!NT_SUCCESS(Status))
  533. {
  534. HeapFree(GlobalHeap, 0, BindData);
  535. return SOCKET_ERROR;
  536. }
  537. /* Get the Socket Structure associate to this Socket*/
  538. Socket = GetSocketStructure(Handle);
  539. if (!Socket)
  540. {
  541. HeapFree(GlobalHeap, 0, BindData);
  542. *lpErrno = WSAENOTSOCK;
  543. return SOCKET_ERROR;
  544. }
  545. /* Set up Address in TDI Format */
  546. BindData->Address.TAAddressCount = 1;
  547. BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
  548. BindData->Address.Address[0].AddressType = SocketAddress->sa_family;
  549. RtlCopyMemory (BindData->Address.Address[0].Address,
  550. SocketAddress->sa_data,
  551. SocketAddressLength - sizeof(SocketAddress->sa_family));
  552. /* Get Address Information */
  553. Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress,
  554. SocketAddressLength,
  555. &SocketInfo);
  556. /* Set the Share Type */
  557. if (Socket->SharedData.ExclusiveAddressUse)
  558. {
  559. BindData->ShareType = AFD_SHARE_EXCLUSIVE;
  560. }
  561. else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard)
  562. {
  563. BindData->ShareType = AFD_SHARE_WILDCARD;
  564. }
  565. else if (Socket->SharedData.ReuseAddresses)
  566. {
  567. BindData->ShareType = AFD_SHARE_REUSE;
  568. }
  569. else
  570. {
  571. BindData->ShareType = AFD_SHARE_UNIQUE;
  572. }
  573. /* Send IOCTL */
  574. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  575. SockEvent,
  576. NULL,
  577. NULL,
  578. &IOSB,
  579. IOCTL_AFD_BIND,
  580. BindData,
  581. 0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/
  582. BindData,
  583. 0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */
  584. /* Wait for return */
  585. if (Status == STATUS_PENDING)
  586. {
  587. WaitForSingleObject(SockEvent, INFINITE);
  588. Status = IOSB.Status;
  589. }
  590. NtClose( SockEvent );
  591. HeapFree(GlobalHeap, 0, BindData);
  592. if (Status != STATUS_SUCCESS)
  593. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  594. /* Set up Socket Data */
  595. Socket->SharedData.State = SocketBound;
  596. Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
  597. if (Socket->HelperEvents & WSH_NOTIFY_BIND)
  598. {
  599. Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
  600. Socket->Handle,
  601. Socket->TdiAddressHandle,
  602. Socket->TdiConnectionHandle,
  603. WSH_NOTIFY_BIND);
  604. if (Status)
  605. {
  606. if (lpErrno) *lpErrno = Status;
  607. return SOCKET_ERROR;
  608. }
  609. }
  610. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  611. }
  612. int
  613. WSPAPI
  614. WSPListen(SOCKET Handle,
  615. int Backlog,
  616. LPINT lpErrno)
  617. {
  618. IO_STATUS_BLOCK IOSB;
  619. AFD_LISTEN_DATA ListenData;
  620. PSOCKET_INFORMATION Socket = NULL;
  621. HANDLE SockEvent;
  622. NTSTATUS Status;
  623. /* Get the Socket Structure associate to this Socket*/
  624. Socket = GetSocketStructure(Handle);
  625. if (!Socket)
  626. {
  627. *lpErrno = WSAENOTSOCK;
  628. return SOCKET_ERROR;
  629. }
  630. if (Socket->SharedData.Listening)
  631. return 0;
  632. Status = NtCreateEvent(&SockEvent,
  633. GENERIC_READ | GENERIC_WRITE,
  634. NULL,
  635. 1,
  636. FALSE);
  637. if( !NT_SUCCESS(Status) )
  638. return -1;
  639. /* Set Up Listen Structure */
  640. ListenData.UseSAN = FALSE;
  641. ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance;
  642. ListenData.Backlog = Backlog;
  643. /* Send IOCTL */
  644. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  645. SockEvent,
  646. NULL,
  647. NULL,
  648. &IOSB,
  649. IOCTL_AFD_START_LISTEN,
  650. &ListenData,
  651. sizeof(ListenData),
  652. NULL,
  653. 0);
  654. /* Wait for return */
  655. if (Status == STATUS_PENDING)
  656. {
  657. WaitForSingleObject(SockEvent, INFINITE);
  658. Status = IOSB.Status;
  659. }
  660. NtClose( SockEvent );
  661. if (Status != STATUS_SUCCESS)
  662. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  663. /* Set to Listening */
  664. Socket->SharedData.Listening = TRUE;
  665. if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
  666. {
  667. Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
  668. Socket->Handle,
  669. Socket->TdiAddressHandle,
  670. Socket->TdiConnectionHandle,
  671. WSH_NOTIFY_LISTEN);
  672. if (Status)
  673. {
  674. if (lpErrno) *lpErrno = Status;
  675. return SOCKET_ERROR;
  676. }
  677. }
  678. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  679. }
  680. int
  681. WSPAPI
  682. WSPSelect(IN int nfds,
  683. IN OUT fd_set *readfds OPTIONAL,
  684. IN OUT fd_set *writefds OPTIONAL,
  685. IN OUT fd_set *exceptfds OPTIONAL,
  686. IN const struct timeval *timeout OPTIONAL,
  687. OUT LPINT lpErrno)
  688. {
  689. IO_STATUS_BLOCK IOSB;
  690. PAFD_POLL_INFO PollInfo;
  691. NTSTATUS Status;
  692. ULONG HandleCount;
  693. LONG OutCount = 0;
  694. ULONG PollBufferSize;
  695. PVOID PollBuffer;
  696. ULONG i, j = 0, x;
  697. HANDLE SockEvent;
  698. BOOL HandleCounted;
  699. LARGE_INTEGER Timeout;
  700. /* Find out how many sockets we have, and how large the buffer needs
  701. * to be */
  702. HandleCount = ( readfds ? readfds->fd_count : 0 ) +
  703. ( writefds ? writefds->fd_count : 0 ) +
  704. ( exceptfds ? exceptfds->fd_count : 0 );
  705. if ( HandleCount == 0 )
  706. {
  707. AFD_DbgPrint(MAX_TRACE,("HandleCount: %u. Return SOCKET_ERROR\n",
  708. HandleCount));
  709. if (lpErrno) *lpErrno = WSAEINVAL;
  710. return SOCKET_ERROR;
  711. }
  712. PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE));
  713. AFD_DbgPrint(MID_TRACE,("HandleCount: %u BufferSize: %u\n",
  714. HandleCount, PollBufferSize));
  715. /* Convert Timeout to NT Format */
  716. if (timeout == NULL)
  717. {
  718. Timeout.u.LowPart = -1;
  719. Timeout.u.HighPart = 0x7FFFFFFF;
  720. AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n"));
  721. }
  722. else
  723. {
  724. Timeout = RtlEnlargedIntegerMultiply
  725. ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000);
  726. /* Negative timeouts are illegal. Since the kernel represents an
  727. * incremental timeout as a negative number, we check for a positive
  728. * result.
  729. */
  730. if (Timeout.QuadPart > 0)
  731. {
  732. if (lpErrno) *lpErrno = WSAEINVAL;
  733. return SOCKET_ERROR;
  734. }
  735. AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n",
  736. timeout->tv_sec, timeout->tv_usec,
  737. Timeout.u.LowPart));
  738. }
  739. Status = NtCreateEvent(&SockEvent,
  740. GENERIC_READ | GENERIC_WRITE,
  741. NULL,
  742. 1,
  743. FALSE);
  744. if( !NT_SUCCESS(Status) )
  745. return SOCKET_ERROR;
  746. /* Allocate */
  747. PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
  748. if (!PollBuffer)
  749. {
  750. if (lpErrno)
  751. *lpErrno = WSAEFAULT;
  752. NtClose(SockEvent);
  753. return SOCKET_ERROR;
  754. }
  755. PollInfo = (PAFD_POLL_INFO)PollBuffer;
  756. RtlZeroMemory( PollInfo, PollBufferSize );
  757. /* Number of handles for AFD to Check */
  758. PollInfo->Exclusive = FALSE;
  759. PollInfo->Timeout = Timeout;
  760. if (readfds != NULL) {
  761. for (i = 0; i < readfds->fd_count; i++, j++)
  762. {
  763. PollInfo->Handles[j].Handle = readfds->fd_array[i];
  764. PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
  765. AFD_EVENT_DISCONNECT |
  766. AFD_EVENT_ABORT |
  767. AFD_EVENT_CLOSE |
  768. AFD_EVENT_ACCEPT;
  769. }
  770. }
  771. if (writefds != NULL)
  772. {
  773. for (i = 0; i < writefds->fd_count; i++, j++)
  774. {
  775. PollInfo->Handles[j].Handle = writefds->fd_array[i];
  776. PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT;
  777. }
  778. }
  779. if (exceptfds != NULL)
  780. {
  781. for (i = 0; i < exceptfds->fd_count; i++, j++)
  782. {
  783. PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
  784. PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
  785. }
  786. }
  787. PollInfo->HandleCount = j;
  788. PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
  789. /* Send IOCTL */
  790. Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
  791. SockEvent,
  792. NULL,
  793. NULL,
  794. &IOSB,
  795. IOCTL_AFD_SELECT,
  796. PollInfo,
  797. PollBufferSize,
  798. PollInfo,
  799. PollBufferSize);
  800. AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
  801. /* Wait for Completition */
  802. if (Status == STATUS_PENDING)
  803. {
  804. WaitForSingleObject(SockEvent, INFINITE);
  805. Status = IOSB.Status;
  806. }
  807. /* Clear the Structures */
  808. if( readfds )
  809. FD_ZERO(readfds);
  810. if( writefds )
  811. FD_ZERO(writefds);
  812. if( exceptfds )
  813. FD_ZERO(exceptfds);
  814. /* Loop through return structure */
  815. HandleCount = PollInfo->HandleCount;
  816. /* Return in FDSET Format */
  817. for (i = 0; i < HandleCount; i++)
  818. {
  819. HandleCounted = FALSE;
  820. for(x = 1; x; x<<=1)
  821. {
  822. switch (PollInfo->Handles[i].Events & x)
  823. {
  824. case AFD_EVENT_RECEIVE:
  825. case AFD_EVENT_DISCONNECT:
  826. case AFD_EVENT_ABORT:
  827. case AFD_EVENT_ACCEPT:
  828. case AFD_EVENT_CLOSE:
  829. AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
  830. PollInfo->Handles[i].Events,
  831. PollInfo->Handles[i].Handle));
  832. if (! HandleCounted)
  833. {
  834. OutCount++;
  835. HandleCounted = TRUE;
  836. }
  837. if( readfds )
  838. FD_SET(PollInfo->Handles[i].Handle, readfds);
  839. break;
  840. case AFD_EVENT_SEND:
  841. case AFD_EVENT_CONNECT:
  842. AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
  843. PollInfo->Handles[i].Events,
  844. PollInfo->Handles[i].Handle));
  845. if (! HandleCounted)
  846. {
  847. OutCount++;
  848. HandleCounted = TRUE;
  849. }
  850. if( writefds )
  851. FD_SET(PollInfo->Handles[i].Handle, writefds);
  852. break;
  853. case AFD_EVENT_OOB_RECEIVE:
  854. case AFD_EVENT_CONNECT_FAIL:
  855. AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
  856. PollInfo->Handles[i].Events,
  857. PollInfo->Handles[i].Handle));
  858. if (! HandleCounted)
  859. {
  860. OutCount++;
  861. HandleCounted = TRUE;
  862. }
  863. if( exceptfds )
  864. FD_SET(PollInfo->Handles[i].Handle, exceptfds);
  865. break;
  866. }
  867. }
  868. }
  869. HeapFree( GlobalHeap, 0, PollBuffer );
  870. NtClose( SockEvent );
  871. if( lpErrno )
  872. {
  873. switch( IOSB.Status )
  874. {
  875. case STATUS_SUCCESS:
  876. case STATUS_TIMEOUT:
  877. *lpErrno = 0;
  878. break;
  879. default:
  880. *lpErrno = WSAEINVAL;
  881. break;
  882. }
  883. AFD_DbgPrint(MID_TRACE,("*lpErrno = %x\n", *lpErrno));
  884. }
  885. AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
  886. return OutCount;
  887. }
  888. SOCKET
  889. WSPAPI
  890. WSPAccept(SOCKET Handle,
  891. struct sockaddr *SocketAddress,
  892. int *SocketAddressLength,
  893. LPCONDITIONPROC lpfnCondition,
  894. DWORD dwCallbackData,
  895. LPINT lpErrno)
  896. {
  897. IO_STATUS_BLOCK IOSB;
  898. PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData;
  899. AFD_ACCEPT_DATA AcceptData;
  900. AFD_DEFER_ACCEPT_DATA DeferData;
  901. AFD_PENDING_ACCEPT_DATA PendingAcceptData;
  902. PSOCKET_INFORMATION Socket = NULL;
  903. NTSTATUS Status;
  904. struct fd_set ReadSet;
  905. struct timeval Timeout;
  906. PVOID PendingData = NULL;
  907. ULONG PendingDataLength = 0;
  908. PVOID CalleeDataBuffer;
  909. WSABUF CallerData, CalleeID, CallerID, CalleeData;
  910. PSOCKADDR RemoteAddress = NULL;
  911. GROUP GroupID = 0;
  912. ULONG CallBack;
  913. WSAPROTOCOL_INFOW ProtocolInfo;
  914. SOCKET AcceptSocket;
  915. PSOCKET_INFORMATION AcceptSocketInfo;
  916. UCHAR ReceiveBuffer[0x1A];
  917. HANDLE SockEvent;
  918. Status = NtCreateEvent(&SockEvent,
  919. GENERIC_READ | GENERIC_WRITE,
  920. NULL,
  921. 1,
  922. FALSE);
  923. if( !NT_SUCCESS(Status) )
  924. {
  925. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  926. return INVALID_SOCKET;
  927. }
  928. /* Dynamic Structure...ugh */
  929. ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
  930. /* Get the Socket Structure associate to this Socket*/
  931. Socket = GetSocketStructure(Handle);
  932. if (!Socket)
  933. {
  934. NtClose(SockEvent);
  935. *lpErrno = WSAENOTSOCK;
  936. return INVALID_SOCKET;
  937. }
  938. /* If this is non-blocking, make sure there's something for us to accept */
  939. FD_ZERO(&ReadSet);
  940. FD_SET(Socket->Handle, &ReadSet);
  941. Timeout.tv_sec=0;
  942. Timeout.tv_usec=0;
  943. if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
  944. {
  945. NtClose(SockEvent);
  946. return INVALID_SOCKET;
  947. }
  948. if (ReadSet.fd_array[0] != Socket->Handle)
  949. {
  950. NtClose(SockEvent);
  951. *lpErrno = WSAEWOULDBLOCK;
  952. return INVALID_SOCKET;
  953. }
  954. /* Send IOCTL */
  955. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  956. SockEvent,
  957. NULL,
  958. NULL,
  959. &IOSB,
  960. IOCTL_AFD_WAIT_FOR_LISTEN,
  961. NULL,
  962. 0,
  963. ListenReceiveData,
  964. 0xA + sizeof(*ListenReceiveData));
  965. /* Wait for return */
  966. if (Status == STATUS_PENDING)
  967. {
  968. WaitForSingleObject(SockEvent, INFINITE);
  969. Status = IOSB.Status;
  970. }
  971. if (!NT_SUCCESS(Status))
  972. {
  973. NtClose( SockEvent );
  974. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  975. return INVALID_SOCKET;
  976. }
  977. if (lpfnCondition != NULL)
  978. {
  979. if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0)
  980. {
  981. /* Find out how much data is pending */
  982. PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
  983. PendingAcceptData.ReturnSize = TRUE;
  984. /* Send IOCTL */
  985. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  986. SockEvent,
  987. NULL,
  988. NULL,
  989. &IOSB,
  990. IOCTL_AFD_GET_PENDING_CONNECT_DATA,
  991. &PendingAcceptData,
  992. sizeof(PendingAcceptData),
  993. &PendingAcceptData,
  994. sizeof(PendingAcceptData));
  995. /* Wait for return */
  996. if (Status == STATUS_PENDING)
  997. {
  998. WaitForSingleObject(SockEvent, INFINITE);
  999. Status = IOSB.Status;
  1000. }
  1001. if (!NT_SUCCESS(Status))
  1002. {
  1003. NtClose( SockEvent );
  1004. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  1005. return INVALID_SOCKET;
  1006. }
  1007. /* How much data to allocate */
  1008. PendingDataLength = IOSB.Information;
  1009. if (PendingDataLength)
  1010. {
  1011. /* Allocate needed space */
  1012. PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
  1013. if (!PendingData)
  1014. {
  1015. MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
  1016. return INVALID_SOCKET;
  1017. }
  1018. /* We want the data now */
  1019. PendingAcceptData.ReturnSize = FALSE;
  1020. /* Send IOCTL */
  1021. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  1022. SockEvent,
  1023. NULL,
  1024. NULL,
  1025. &IOSB,
  1026. IOCTL_AFD_GET_PENDING_CONNECT_DATA,
  1027. &PendingAcceptData,
  1028. sizeof(PendingAcceptData),
  1029. PendingData,
  1030. PendingDataLength);
  1031. /* Wait for return */
  1032. if (Status == STATUS_PENDING)
  1033. {
  1034. WaitForSingleObject(SockEvent, INFINITE);
  1035. Status = IOSB.Status;
  1036. }
  1037. if (!NT_SUCCESS(Status))
  1038. {
  1039. NtClose( SockEvent );
  1040. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  1041. return INVALID_SOCKET;
  1042. }
  1043. }
  1044. }
  1045. if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
  1046. {
  1047. /* I don't support this yet */
  1048. }
  1049. /* Build Callee ID */
  1050. CalleeID.buf = (PVOID)Socket->LocalAddress;
  1051. CalleeID.len = Socket->SharedData.SizeOfLocalAddress;
  1052. RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
  1053. if (!RemoteAddress)
  1054. {
  1055. MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
  1056. return INVALID_SOCKET;
  1057. }
  1058. /* Set up Address in SOCKADDR Format */
  1059. RtlCopyMemory (RemoteAddress,
  1060. &ListenReceiveData->Address.Address[0].AddressType,
  1061. sizeof(*RemoteAddress));
  1062. /* Build Caller ID */
  1063. CallerID.buf = (PVOID)RemoteAddress;
  1064. CallerID.len = sizeof(*RemoteAddress);
  1065. /* Build Caller Data */
  1066. CallerData.buf = PendingData;
  1067. CallerData.len = PendingDataLength;
  1068. /* Check if socket supports Conditional Accept */
  1069. if (Socket->SharedData.UseDelayedAcceptance != 0)
  1070. {
  1071. /* Allocate Buffer for Callee Data */
  1072. CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
  1073. if (!CalleeDataBuffer) {
  1074. MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
  1075. return INVALID_SOCKET;
  1076. }
  1077. CalleeData.buf = CalleeDataBuffer;
  1078. CalleeData.len = 4096;
  1079. }
  1080. else
  1081. {
  1082. /* Nothing */
  1083. CalleeData.buf = 0;
  1084. CalleeData.len = 0;
  1085. }
  1086. /* Call the Condition Function */
  1087. CallBack = (lpfnCondition)(&CallerID,
  1088. CallerData.buf == NULL ? NULL : &CallerData,
  1089. NULL,
  1090. NULL,
  1091. &CalleeID,
  1092. CalleeData.buf == NULL ? NULL : &CalleeData,
  1093. &GroupID,
  1094. dwCallbackData);
  1095. if (((CallBack == CF_ACCEPT) && GroupID) != 0)
  1096. {
  1097. /* TBD: Check for Validity */
  1098. }
  1099. if (CallBack == CF_ACCEPT)
  1100. {
  1101. if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
  1102. {
  1103. /* I don't support this yet */
  1104. }
  1105. if (CalleeData.buf)
  1106. {
  1107. // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
  1108. }
  1109. }
  1110. else
  1111. {
  1112. /* Callback rejected. Build Defer Structure */
  1113. DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
  1114. DeferData.RejectConnection = (CallBack == CF_REJECT);
  1115. /* Send IOCTL */
  1116. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  1117. SockEvent,
  1118. NULL,
  1119. NULL,
  1120. &IOSB,
  1121. IOCTL_AFD_DEFER_ACCEPT,
  1122. &DeferData,
  1123. sizeof(DeferData),
  1124. NULL,
  1125. 0);
  1126. /* Wait for return */
  1127. if (Status == STATUS_PENDING)
  1128. {
  1129. WaitForSingleObject(SockEvent, INFINITE);
  1130. Status = IOSB.Status;
  1131. }
  1132. NtClose( SockEvent );
  1133. if (!NT_SUCCESS(Status))
  1134. {
  1135. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  1136. return INVALID_SOCKET;
  1137. }
  1138. if (CallBack == CF_REJECT )
  1139. {
  1140. *lpErrno = WSAECONNREFUSED;
  1141. return INVALID_SOCKET;
  1142. }
  1143. else
  1144. {
  1145. *lpErrno = WSAECONNREFUSED;
  1146. return INVALID_SOCKET;
  1147. }
  1148. }
  1149. }
  1150. /* Create a new Socket */
  1151. ProtocolInfo.dwCatalogEntryId = Socket->SharedData.CatalogEntryId;
  1152. ProtocolInfo.dwServiceFlags1 = Socket->SharedData.ServiceFlags1;
  1153. ProtocolInfo.dwProviderFlags = Socket->SharedData.ProviderFlags;
  1154. AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily,
  1155. Socket->SharedData.SocketType,
  1156. Socket->SharedData.Protocol,
  1157. &ProtocolInfo,
  1158. GroupID,
  1159. Socket->SharedData.CreateFlags,
  1160. lpErrno);
  1161. if (AcceptSocket == INVALID_SOCKET)
  1162. return INVALID_SOCKET;
  1163. /* Set up the Accept Structure */
  1164. AcceptData.ListenHandle = (HANDLE)AcceptSocket;
  1165. AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
  1166. /* Send IOCTL to Accept */
  1167. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  1168. SockEvent,
  1169. NULL,
  1170. NULL,
  1171. &IOSB,
  1172. IOCTL_AFD_ACCEPT,
  1173. &AcceptData,
  1174. sizeof(AcceptData),
  1175. NULL,
  1176. 0);
  1177. /* Wait for return */
  1178. if (Status == STATUS_PENDING)
  1179. {
  1180. WaitForSingleObject(SockEvent, INFINITE);
  1181. Status = IOSB.Status;
  1182. }
  1183. if (!NT_SUCCESS(Status))
  1184. {
  1185. NtClose(SockEvent);
  1186. WSPCloseSocket( AcceptSocket, lpErrno );
  1187. MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  1188. return INVALID_SOCKET;
  1189. }
  1190. AcceptSocketInfo = GetSocketStructure(AcceptSocket);
  1191. if (!AcceptSocketInfo)
  1192. {
  1193. NtClose(SockEvent);
  1194. WSPCloseSocket( AcceptSocket, lpErrno );
  1195. MsafdReturnWithErrno( STATUS_INVALID_CONNECTION, lpErrno, 0, NULL );
  1196. return INVALID_SOCKET;
  1197. }
  1198. AcceptSocketInfo->SharedData.State = SocketConnected;
  1199. /* Return Address in SOCKADDR FORMAT */
  1200. if( SocketAddress )
  1201. {
  1202. RtlCopyMemory (SocketAddress,
  1203. &ListenReceiveData->Address.Address[0].AddressType,
  1204. sizeof(*RemoteAddress));
  1205. if( SocketAddressLength )
  1206. *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength;
  1207. }
  1208. NtClose( SockEvent );
  1209. /* Re-enable Async Event */
  1210. SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
  1211. AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket));
  1212. if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
  1213. {
  1214. Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
  1215. Socket->Handle,
  1216. Socket->TdiAddressHandle,
  1217. Socket->TdiConnectionHandle,
  1218. WSH_NOTIFY_ACCEPT);
  1219. if (Status)
  1220. {
  1221. if (lpErrno) *lpErrno = Status;
  1222. return INVALID_SOCKET;
  1223. }
  1224. }
  1225. *lpErrno = 0;
  1226. /* Return Socket */
  1227. return AcceptSocket;
  1228. }
  1229. int
  1230. WSPAPI
  1231. WSPConnect(SOCKET Handle,
  1232. const struct sockaddr * SocketAddress,
  1233. int SocketAddressLength,
  1234. LPWSABUF lpCallerData,
  1235. LPWSABUF lpCalleeData,
  1236. LPQOS lpSQOS,
  1237. LPQOS lpGQOS,
  1238. LPINT lpErrno)
  1239. {
  1240. IO_STATUS_BLOCK IOSB;
  1241. PAFD_CONNECT_INFO ConnectInfo = NULL;
  1242. PSOCKET_INFORMATION Socket;
  1243. NTSTATUS Status;
  1244. INT Errno;
  1245. ULONG ConnectDataLength;
  1246. ULONG InConnectDataLength;
  1247. INT BindAddressLength;
  1248. PSOCKADDR BindAddress;
  1249. HANDLE SockEvent;
  1250. int SocketDataLength;
  1251. Status = NtCreateEvent(&SockEvent,
  1252. GENERIC_READ | GENERIC_WRITE,
  1253. NULL,
  1254. 1,
  1255. FALSE);
  1256. if (!NT_SUCCESS(Status))
  1257. return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
  1258. AFD_DbgPrint(MID_TRACE,("Called\n"));
  1259. /* Get the Socket Structure associate to this Socket*/
  1260. Socket = GetSocketStructure(Handle);
  1261. if (!Socket)
  1262. {
  1263. NtClose(SockEvent);
  1264. if (lpErrno) *lpErrno = WSAENOTSOCK;
  1265. return SOCKET_ERROR;
  1266. }
  1267. /* Bind us First */
  1268. if (Socket->SharedData.State == SocketOpen)
  1269. {
  1270. /* Get the Wildcard Address */
  1271. BindAddressLength = Socket->HelperData->MaxWSAddressLength;
  1272. BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
  1273. if (!BindAddress)
  1274. {
  1275. NtClose(SockEvent);
  1276. return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
  1277. }
  1278. Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
  1279. BindAddress,
  1280. &BindAddressLength);
  1281. /* Bind it */
  1282. if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
  1283. return SOCKET_ERROR;
  1284. }
  1285. /* Set the Connect Data */
  1286. if (lpCallerData != NULL)
  1287. {
  1288. ConnectDataLength = lpCallerData->len;
  1289. Status = NtDeviceIoControlFile((HANDLE)Handle,
  1290. SockEvent,
  1291. NULL,
  1292. NULL,
  1293. &IOSB,
  1294. IOCTL_AFD_SET_CONNECT_DATA,
  1295. lpCallerData->buf,
  1296. ConnectDataLength,
  1297. NULL,
  1298. 0);
  1299. /* Wait for return */
  1300. if (Status == STATUS_PENDING)
  1301. {
  1302. WaitForSingleObject(SockEvent, INFINITE);
  1303. Status = IOSB.Status;
  1304. }
  1305. if (Status != STATUS_SUCCESS)
  1306. goto notify;
  1307. }
  1308. /* Calculate the size of SocketAddress->sa_data */
  1309. SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
  1310. /* Allocate a connection info buffer with SocketDataLength bytes of payload */
  1311. ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
  1312. FIELD_OFFSET(AFD_CONNECT_INFO,
  1313. RemoteAddress.Address[0].Address[SocketDataLength]));
  1314. if (!ConnectInfo)
  1315. {
  1316. Status = STATUS_INSUFFICIENT_RESOURCES;
  1317. goto notify;
  1318. }
  1319. /* Set up Address in TDI Format */
  1320. ConnectInfo->RemoteAddress.TAAddressCount = 1;
  1321. ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength;
  1322. ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family;
  1323. RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address,
  1324. SocketAddress->sa_data,
  1325. SocketDataLength);
  1326. /*
  1327. * Disable FD_WRITE and FD_CONNECT
  1328. * The latter fixes a race condition where the FD_CONNECT is re-enabled
  1329. * at the end of this function right after the Async Thread disables it.
  1330. * This should only happen at the *next* WSPConnect
  1331. */
  1332. if (Socket->SharedData.AsyncEvents & FD_CONNECT)
  1333. {
  1334. Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE;
  1335. }
  1336. /* Tell AFD that we want Connection Data back, have it allocate a buffer */
  1337. if (lpCalleeData != NULL)
  1338. {
  1339. InConnectDataLength = lpCalleeData->len;
  1340. Status = NtDeviceIoControlFile((HANDLE)Handle,
  1341. SockEvent,
  1342. NULL,
  1343. NULL,
  1344. &IOSB,
  1345. IOCTL_AFD_SET_CONNECT_DATA_SIZE,
  1346. &InConnectDataLength,
  1347. sizeof(InConnectDataLength),
  1348. NULL,
  1349. 0);
  1350. /* Wait for return */
  1351. if (Status == STATUS_PENDING)
  1352. {
  1353. WaitForSingleObject(SockEvent, INFINITE);
  1354. Status = IOSB.Status;
  1355. }
  1356. if (Status != STATUS_SUCCESS)
  1357. goto notify;
  1358. }
  1359. /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
  1360. ConnectInfo->Root = 0;
  1361. ConnectInfo->UseSAN = FALSE;
  1362. ConnectInfo->Unknown = 0;
  1363. /* FIXME: Handle Async Connect */
  1364. if (Socket->SharedData.NonBlocking)
  1365. {
  1366. AFD_DbgPrint(MIN_TRACE, ("Async Connect UNIMPLEMENTED!\n"));
  1367. }
  1368. /* Send IOCTL */
  1369. Status = NtDeviceIoControlFile((HANDLE)Handle,
  1370. SockEvent,
  1371. NULL,
  1372. NULL,
  1373. &IOSB,
  1374. IOCTL_AFD_CONNECT,
  1375. ConnectInfo,
  1376. 0x22,
  1377. NULL,
  1378. 0);
  1379. /* Wait for return */
  1380. if (Status == STATUS_PENDING)
  1381. {
  1382. WaitForSingleObject(SockEvent, INFINITE);
  1383. Status = IOSB.Status;
  1384. }
  1385. if (Status != STATUS_SUCCESS)
  1386. goto notify;
  1387. Socket->SharedData.State = SocketConnected;
  1388. Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
  1389. /* Get any pending connect data */
  1390. if (lpCalleeData != NULL)
  1391. {
  1392. Status = NtDeviceIoControlFile((HANDLE)Handle,
  1393. SockEvent,
  1394. NULL,
  1395. NULL,
  1396. &IOSB,
  1397. IOCTL_AFD_GET_CONNECT_DATA,
  1398. NULL,
  1399. 0,
  1400. lpCalleeData->buf,
  1401. lpCalleeData->len);
  1402. /* Wait for return */
  1403. if (Status == STATUS_PENDING)
  1404. {
  1405. WaitForSingleObject(SockEvent, INFINITE);
  1406. Status = IOSB.Status;
  1407. }
  1408. }
  1409. AFD_DbgPrint(MID_TRACE,("Ending\n"));
  1410. notify:
  1411. if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
  1412. /* Re-enable Async Event */
  1413. SockReenableAsyncSelectEvent(Socket, FD_WRITE);
  1414. /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
  1415. SockReenableAsyncSelectEvent(Socket, FD_CONNECT);
  1416. NtClose(SockEvent);
  1417. if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
  1418. {
  1419. Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
  1420. Socket->Handle,
  1421. Socket->TdiAddressHandle,
  1422. Socket->TdiConnectionHandle,
  1423. WSH_NOTIFY_CONNECT);
  1424. if (Errno)
  1425. {
  1426. if (lpErrno) *lpErrno = Errno;
  1427. return SOCKET_ERROR;
  1428. }
  1429. }
  1430. else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
  1431. {
  1432. Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
  1433. Socket->Handle,
  1434. Socket->TdiAddressHandle,
  1435. Socket->TdiConnectionHandle,
  1436. WSH_NOTIFY_CONNECT_ERROR);
  1437. if (Errno)
  1438. {
  1439. if (lpErrno) *lpErrno = Errno;
  1440. return SOCKET_ERROR;
  1441. }
  1442. }
  1443. return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
  1444. }
  1445. int
  1446. WSPAPI
  1447. WSPShutdown(SOCKET Handle,
  1448. int HowTo,
  1449. LPINT lpErrno)
  1450. {
  1451. IO_STATUS_BLOCK IOSB;
  1452. AFD_DISCONNECT_INFO DisconnectInfo;
  1453. PSOCKET_INFORMATION Socket = NULL;
  1454. NTSTATUS Status;
  1455. HANDLE SockEvent;
  1456. Status = NtCreateEvent(&SockEvent,
  1457. GENERIC_READ | GENERIC_WRITE,
  1458. NULL,
  1459. 1,
  1460. FALSE);
  1461. if( !NT_SUCCESS(Status) )
  1462. return -1;
  1463. AFD_DbgPrint(MID_TRACE,("Called\n"));
  1464. /* Get the Socket Structure associate to this Socket*/
  1465. Socket = GetSocketStructure(Handle);
  1466. if (!Socket)
  1467. {
  1468. NtClose(SockEvent);
  1469. *lpErrno = WSAENOTSOCK;
  1470. return SOCKET_ERROR;
  1471. }
  1472. /* Set AFD Disconnect Type */
  1473. switch (HowTo)
  1474. {
  1475. case SD_RECEIVE:
  1476. DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV;
  1477. Socket->SharedData.ReceiveShutdown = TRUE;
  1478. break;
  1479. case SD_SEND:
  1480. DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND;
  1481. Socket->SharedData.SendShutdown = TRUE;
  1482. break;
  1483. case SD_BOTH:
  1484. DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND;
  1485. Socket->SharedData.ReceiveShutdown = TRUE;
  1486. Socket->SharedData.SendShutdown = TRUE;
  1487. break;
  1488. }
  1489. DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
  1490. /* Send IOCTL */
  1491. Status = NtDeviceIoControlFile((HANDLE)Handle,
  1492. SockEvent,
  1493. NULL,
  1494. NULL,
  1495. &IOSB,
  1496. IOCTL_AFD_DISCONNECT,
  1497. &DisconnectInfo,
  1498. sizeof(DisconnectInfo),
  1499. NULL,
  1500. 0);
  1501. /* Wait for return */
  1502. if (Status == STATUS_PENDING)
  1503. {
  1504. WaitForSingleObject(SockEvent, INFINITE);
  1505. Status = IOSB.Status;
  1506. }
  1507. AFD_DbgPrint(MID_TRACE,("Ending\n"));
  1508. NtClose( SockEvent );
  1509. return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
  1510. }
  1511. INT
  1512. WSPAPI
  1513. WSPGetSockName(IN SOCKET Handle,
  1514. OUT LPSOCKADDR Name,
  1515. IN OUT LPINT NameLength,
  1516. OUT LPINT lpErrno)
  1517. {
  1518. IO_STATUS_BLOCK IOSB;
  1519. ULONG TdiAddressSize;
  1520. PTDI_ADDRESS_INFO TdiAddress;
  1521. PTRANSPORT_ADDRESS SocketAddress;
  1522. PSOCKET_INFORMATION Socket = NULL;
  1523. NTSTATUS Status;
  1524. HANDLE SockEvent;
  1525. Status = NtCreateEvent(&SockEvent,
  1526. GENERIC_READ | GENERIC_WRITE,
  1527. NULL,
  1528. 1,
  1529. FALSE);
  1530. if( !NT_SUCCESS(Status) )
  1531. return SOCKET_ERROR;
  1532. /* Get the Socket Structure associate to this Socket*/
  1533. Socket = GetSocketStructure(Handle);
  1534. if (!Socket)
  1535. {
  1536. NtClose(SockEvent);
  1537. *lpErrno = WSAENOTSOCK;
  1538. return SOCKET_ERROR;
  1539. }
  1540. if (!Name || !NameLength)
  1541. {
  1542. NtClose(SockEvent);
  1543. *lpErrno = WSAEFAULT;
  1544. return SOCKET_ERROR;
  1545. }
  1546. /* Allocate a buffer for the address */
  1547. TdiAddressSize =
  1548. sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress;
  1549. TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
  1550. if ( TdiAddress == NULL )
  1551. {
  1552. NtClose( SockEvent );
  1553. *lpErrno = WSAENOBUFS;
  1554. return SOCKET_ERROR;
  1555. }
  1556. SocketAddress = &TdiAddress->Address;
  1557. /* Send IOCTL */
  1558. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  1559. SockEvent,
  1560. NULL,
  1561. NULL,
  1562. &IOSB,
  1563. IOCTL_AFD_GET_SOCK_NAME,
  1564. NULL,
  1565. 0,
  1566. TdiAddress,
  1567. TdiAddressSize);
  1568. /* Wait for return */
  1569. if (Status == STATUS_PENDING)
  1570. {
  1571. WaitForSingleObject(SockEvent, INFINITE);
  1572. Status = IOSB.Status;
  1573. }
  1574. NtClose( SockEvent );
  1575. if (NT_SUCCESS(Status))
  1576. {
  1577. if (*NameLength >= Socket->SharedData.SizeOfLocalAddress)
  1578. {
  1579. Name->sa_family = SocketAddress->Address[0].AddressType;
  1580. RtlCopyMemory (Name->sa_data,
  1581. SocketAddress->Address[0].Address,
  1582. SocketAddress->Address[0].AddressLength);
  1583. *NameLength = Socket->SharedData.SizeOfLocalAddress;
  1584. AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n",
  1585. *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
  1586. ((struct sockaddr_in *)Name)->sin_port));
  1587. HeapFree(GlobalHeap, 0, TdiAddress);
  1588. return 0;
  1589. }
  1590. else
  1591. {
  1592. HeapFree(GlobalHeap, 0, TdiAddress);
  1593. *lpErrno = WSAEFAULT;
  1594. return SOCKET_ERROR;
  1595. }
  1596. }
  1597. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  1598. }
  1599. INT
  1600. WSPAPI
  1601. WSPGetPeerName(IN SOCKET s,
  1602. OUT LPSOCKADDR Name,
  1603. IN OUT LPINT NameLength,
  1604. OUT LPINT lpErrno)
  1605. {
  1606. IO_STATUS_BLOCK IOSB;
  1607. ULONG TdiAddressSize;
  1608. PTRANSPORT_ADDRESS SocketAddress;
  1609. PSOCKET_INFORMATION Socket = NULL;
  1610. NTSTATUS Status;
  1611. HANDLE SockEvent;
  1612. Status = NtCreateEvent(&SockEvent,
  1613. GENERIC_READ | GENERIC_WRITE,
  1614. NULL,
  1615. 1,
  1616. FALSE);
  1617. if( !NT_SUCCESS(Status) )
  1618. return SOCKET_ERROR;
  1619. /* Get the Socket Structure associate to this Socket*/
  1620. Socket = GetSocketStructure(s);
  1621. if (!Socket)
  1622. {
  1623. NtClose(SockEvent);
  1624. *lpErrno = WSAENOTSOCK;
  1625. return SOCKET_ERROR;
  1626. }
  1627. if (Socket->SharedData.State != SocketConnected)
  1628. {
  1629. NtClose(SockEvent);
  1630. *lpErrno = WSAENOTCONN;
  1631. return SOCKET_ERROR;
  1632. }
  1633. if (!Name || !NameLength)
  1634. {
  1635. NtClose(SockEvent);
  1636. *lpErrno = WSAEFAULT;
  1637. return SOCKET_ERROR;
  1638. }
  1639. /* Allocate a buffer for the address */
  1640. TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress;
  1641. SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
  1642. if ( SocketAddress == NULL )
  1643. {
  1644. NtClose( SockEvent );
  1645. *lpErrno = WSAENOBUFS;
  1646. return SOCKET_ERROR;
  1647. }
  1648. /* Send IOCTL */
  1649. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  1650. SockEvent,
  1651. NULL,
  1652. NULL,
  1653. &IOSB,
  1654. IOCTL_AFD_GET_PEER_NAME,
  1655. NULL,
  1656. 0,
  1657. SocketAddress,
  1658. TdiAddressSize);
  1659. /* Wait for return */
  1660. if (Status == STATUS_PENDING)
  1661. {
  1662. WaitForSingleObject(SockEvent, INFINITE);
  1663. Status = IOSB.Status;
  1664. }
  1665. NtClose( SockEvent );
  1666. if (NT_SUCCESS(Status))
  1667. {
  1668. if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress)
  1669. {
  1670. Name->sa_family = SocketAddress->Address[0].AddressType;
  1671. RtlCopyMemory (Name->sa_data,
  1672. SocketAddress->Address[0].Address,
  1673. SocketAddress->Address[0].AddressLength);
  1674. *NameLength = Socket->SharedData.SizeOfRemoteAddress;
  1675. AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n",
  1676. *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
  1677. ((struct sockaddr_in *)Name)->sin_port));
  1678. HeapFree(GlobalHeap, 0, SocketAddress);
  1679. return 0;
  1680. }
  1681. else
  1682. {
  1683. HeapFree(GlobalHeap, 0, SocketAddress);
  1684. *lpErrno = WSAEFAULT;
  1685. return SOCKET_ERROR;
  1686. }
  1687. }
  1688. return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
  1689. }
  1690. INT
  1691. WSPAPI
  1692. WSPIoctl(IN SOCKET Handle,
  1693. IN DWORD dwIoControlCode,
  1694. IN LPVOID lpvInBuffer,
  1695. IN DWORD cbInBuffer,
  1696. OUT LPVOID lpvOutBuffer,
  1697. IN DWORD cbOutBuffer,
  1698. OUT LPDWORD lpcbBytesReturned,
  1699. IN LPWSAOVERLAPPED lpOverlapped,
  1700. IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  1701. IN LPWSATHREADID lpThreadId,
  1702. OUT LPINT lpErrno)
  1703. {
  1704. PSOCKET_INFORMATION Socket = NULL;
  1705. BOOLEAN NeedsCompletion;
  1706. BOOLEAN NonBlocking;
  1707. /* Get the Socket Structure associate to this Socket*/
  1708. Socket = GetSocketStructure(Handle);
  1709. if (!Socket)
  1710. {
  1711. *lpErrno = WSAENOTSOCK;
  1712. return SOCKET_ERROR;
  1713. }
  1714. *lpcbBytesReturned = 0;
  1715. switch( dwIoControlCode )
  1716. {
  1717. case FIONBIO:
  1718. if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
  1719. {
  1720. *lpErrno = WSAEFAULT;
  1721. return SOCKET_ERROR;
  1722. }
  1723. NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
  1724. Socket->SharedData.NonBlocking = NonBlocking ? 1 : 0;
  1725. *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL);
  1726. if (*lpErrno != NO_ERROR)
  1727. return SOCKET_ERROR;
  1728. else
  1729. return NO_ERROR;
  1730. case FIONREAD:
  1731. if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
  1732. {
  1733. *lpErrno = WSAEFAULT;
  1734. return SOCKET_ERROR;
  1735. }
  1736. *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
  1737. if (*lpErrno != NO_ERROR)
  1738. return SOCKET_ERROR;
  1739. else
  1740. {
  1741. *lpcbBytesReturned = sizeof(ULONG);
  1742. return NO_ERROR;
  1743. }
  1744. case SIO_GET_EXTENSION_FUNCTION_POINTER:
  1745. *lpErrno = WSAEINVAL;
  1746. return SOCKET_ERROR;
  1747. default:
  1748. *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
  1749. Handle,
  1750. Socket->TdiAddressHandle,
  1751. Socket->TdiConnectionHandle,
  1752. dwIoControlCode,
  1753. lpvInBuffer,
  1754. cbInBuffer,
  1755. lpvOutBuffer,
  1756. cbOutBuffer,
  1757. lpcbBytesReturned,
  1758. lpOverlapped,
  1759. lpCompletionRoutine,
  1760. (LPBOOL)&NeedsCompletion);
  1761. if (*lpErrno != NO_ERROR)
  1762. return SOCKET_ERROR;
  1763. else
  1764. return NO_ERROR;
  1765. }
  1766. }
  1767. INT
  1768. WSPAPI
  1769. WSPGetSockOpt(IN SOCKET Handle,
  1770. IN INT Level,
  1771. IN INT OptionName,
  1772. OUT CHAR FAR* OptionValue,
  1773. IN OUT LPINT OptionLength,
  1774. OUT LPINT lpErrno)
  1775. {
  1776. PSOCKET_INFORMATION Socket = NULL;
  1777. PVOID Buffer;
  1778. INT BufferSize;
  1779. BOOL BoolBuffer;
  1780. /* Get the Socket Structure associate to this Socket*/
  1781. Socket = GetSocketStructure(Handle);
  1782. if (Socket == NULL)
  1783. {
  1784. *lpErrno = WSAENOTSOCK;
  1785. return SOCKET_ERROR;
  1786. }
  1787. AFD_DbgPrint(MID_TRACE, ("Called\n"));
  1788. switch (Level)
  1789. {
  1790. case SOL_SOCKET:
  1791. switch (OptionName)
  1792. {
  1793. case SO_TYPE:
  1794. Buffer = &Socket->SharedData.SocketType;
  1795. BufferSize = sizeof(INT);
  1796. break;
  1797. case SO_RCVBUF:
  1798. Buffer = &Socket->SharedData.SizeOfRecvBuffer;
  1799. BufferSize = sizeof(INT);
  1800. break;
  1801. case SO_SNDBUF:
  1802. Buffer = &Socket->SharedData.SizeOfSendBuffer;
  1803. BufferSize = sizeof(INT);
  1804. break;
  1805. case SO_ACCEPTCONN:
  1806. BoolBuffer = Socket->SharedData.Listening;
  1807. Buffer = &BoolBuffer;
  1808. BufferSize = sizeof(BOOL);
  1809. break;
  1810. case SO_BROADCAST:
  1811. BoolBuffer = Socket->SharedData.Broadcast;
  1812. Buffer = &BoolBuffer;
  1813. BufferSize = sizeof(BOOL);
  1814. break;
  1815. case SO_DEBUG:
  1816. BoolBuffer = Socket->SharedData.Debug;
  1817. Buffer = &BoolBuffer;
  1818. BufferSize = sizeof(BOOL);
  1819. break;
  1820. case SO_DONTLINGER:
  1821. BoolBuffer = (Socket->SharedData.LingerData.l_onoff == 0);
  1822. Buffer = &BoolBuffer;
  1823. BufferSize = sizeof(BOOL);
  1824. break;
  1825. case SO_LINGER:
  1826. Buffer = &Socket->SharedData.LingerData;
  1827. BufferSize = sizeof(struct linger);
  1828. break;
  1829. /* case SO_CONDITIONAL_ACCEPT: */
  1830. case SO_DONTROUTE:
  1831. case SO_ERROR:
  1832. case SO_GROUP_ID:
  1833. case SO_GROUP_PRIORITY:
  1834. case SO_KEEPALIVE:
  1835. case SO_MAX_MSG_SIZE:
  1836. case SO_OOBINLINE:
  1837. case SO_PROTOCOL_INFO:
  1838. case SO_REUSEADDR:
  1839. AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n",
  1840. OptionName));
  1841. default:
  1842. *lpErrno = WSAEINVAL;
  1843. return SOCKET_ERROR;
  1844. }
  1845. if (*OptionLength < BufferSize)
  1846. {
  1847. *lpErrno = WSAEFAULT;
  1848. *OptionLength = BufferSize;
  1849. return SOCKET_ERROR;
  1850. }
  1851. RtlCopyMemory(OptionValue, Buffer, BufferSize);
  1852. return 0;
  1853. case IPPROTO_TCP: /* FIXME */
  1854. default:
  1855. *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
  1856. Handle,
  1857. Socket->TdiAddressHandle,
  1858. Socket->TdiConnectionHandle,
  1859. Level,
  1860. OptionName,
  1861. OptionValue,
  1862. (LPINT)OptionLength);
  1863. return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
  1864. }
  1865. }
  1866. INT
  1867. WSPAPI
  1868. WSPSetSockOpt(
  1869. IN SOCKET s,
  1870. IN INT level,
  1871. IN INT optname,
  1872. IN CONST CHAR FAR* optval,
  1873. IN INT optlen,
  1874. OUT LPINT lpErrno)
  1875. {
  1876. PSOCKET_INFORMATION Socket;
  1877. /* Get the Socket Structure associate to this Socket*/
  1878. Socket = GetSocketStructure(s);
  1879. if (Socket == NULL)
  1880. {
  1881. *lpErrno = WSAENOTSOCK;
  1882. return SOCKET_ERROR;
  1883. }
  1884. /* FIXME: We should handle some more cases here */
  1885. if (level == SOL_SOCKET)
  1886. {
  1887. switch (optname)
  1888. {
  1889. case SO_BROADCAST:
  1890. if (optlen < sizeof(BOOL))
  1891. {
  1892. *lpErrno = WSAEFAULT;
  1893. return SOCKET_ERROR;
  1894. }
  1895. Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
  1896. return 0;
  1897. case SO_DONTLINGER:
  1898. if (optlen < sizeof(BOOL))
  1899. {
  1900. *lpErrno = WSAEFAULT;
  1901. return SOCKET_ERROR;
  1902. }
  1903. Socket->SharedData.LingerData.l_onoff = (*optval != 0) ? 0 : 1;
  1904. return 0;
  1905. case SO_LINGER:
  1906. if (optlen < sizeof(struct linger))
  1907. {
  1908. *lpErrno = WSAEFAULT;
  1909. return SOCKET_ERROR;
  1910. }
  1911. RtlCopyMemory(&Socket->SharedData.LingerData,
  1912. optval,
  1913. sizeof(struct linger));
  1914. return 0;
  1915. case SO_SNDBUF:
  1916. if (optlen < sizeof(DWORD))
  1917. {
  1918. *lpErrno = WSAEFAULT;
  1919. return SOCKET_ERROR;
  1920. }
  1921. /* TODO: The total per-socket buffer space reserved for sends */
  1922. AFD_DbgPrint(MIN_TRACE,("Setting send buf to %x is not implemented yet\n", optval));
  1923. return 0;
  1924. default:
  1925. AFD_DbgPrint(MIN_TRACE,("Unknown optname %x\n", optname));
  1926. break;
  1927. }
  1928. }
  1929. *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
  1930. s,
  1931. Socket->TdiAddressHandle,
  1932. Socket->TdiConnectionHandle,
  1933. level,
  1934. optname,
  1935. (PCHAR)optval,
  1936. optlen);
  1937. return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
  1938. }
  1939. /*
  1940. * FUNCTION: Initialize service provider for a client
  1941. * ARGUMENTS:
  1942. * wVersionRequested = Highest WinSock SPI version that the caller can use
  1943. * lpWSPData = Address of WSPDATA structure to initialize
  1944. * lpProtocolInfo = Pointer to structure that defines the desired protocol
  1945. * UpcallTable = Pointer to upcall table of the WinSock DLL
  1946. * lpProcTable = Address of procedure table to initialize
  1947. * RETURNS:
  1948. * Status of operation
  1949. */
  1950. INT
  1951. WSPAPI
  1952. WSPStartup(IN WORD wVersionRequested,
  1953. OUT LPWSPDATA lpWSPData,
  1954. IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
  1955. IN WSPUPCALLTABLE UpcallTable,
  1956. OUT LPWSPPROC_TABLE lpProcTable)
  1957. {
  1958. NTSTATUS Status;
  1959. AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
  1960. Status = NO_ERROR;
  1961. Upcalls = UpcallTable;
  1962. if (Status == NO_ERROR)
  1963. {
  1964. lpProcTable->lpWSPAccept = WSPAccept;
  1965. lpProcTable->lpWSPAddressToString = WSPAddressToString;
  1966. lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
  1967. lpProcTable->lpWSPBind = WSPBind;
  1968. lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
  1969. lpProcTable->lpWSPCleanup = WSPCleanup;
  1970. lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
  1971. lpProcTable->lpWSPConnect = WSPConnect;
  1972. lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
  1973. lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
  1974. lpProcTable->lpWSPEventSelect = WSPEventSelect;
  1975. lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
  1976. lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
  1977. lpProcTable->lpWSPGetSockName = WSPGetSockName;
  1978. lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
  1979. lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
  1980. lpProcTable->lpWSPIoctl = WSPIoctl;
  1981. lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
  1982. lpProcTable->lpWSPListen = WSPListen;
  1983. lpProcTable->lpWSPRecv = WSPRecv;
  1984. lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
  1985. lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
  1986. lpProcTable->lpWSPSelect = WSPSelect;
  1987. lpProcTable->lpWSPSend = WSPSend;
  1988. lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
  1989. lpProcTable->lpWSPSendTo = WSPSendTo;
  1990. lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
  1991. lpProcTable->lpWSPShutdown = WSPShutdown;
  1992. lpProcTable->lpWSPSocket = WSPSocket;
  1993. lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
  1994. lpWSPData->wVersion = MAKEWORD(2, 2);
  1995. lpWSPData->wHighVersion = MAKEWORD(2, 2);
  1996. }
  1997. AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
  1998. return Status;
  1999. }
  2000. /*
  2001. * FUNCTION: Cleans up service provider for a client
  2002. * ARGUMENTS:
  2003. * lpErrno = Address of buffer for error information
  2004. * RETURNS:
  2005. * 0 if successful, or SOCKET_ERROR if not
  2006. */
  2007. INT
  2008. WSPAPI
  2009. WSPCleanup(OUT LPINT lpErrno)
  2010. {
  2011. AFD_DbgPrint(MAX_TRACE, ("\n"));
  2012. AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
  2013. *lpErrno = NO_ERROR;
  2014. return 0;
  2015. }
  2016. int
  2017. GetSocketInformation(PSOCKET_INFORMATION Socket,
  2018. ULONG AfdInformationClass,
  2019. PBOOLEAN Boolean OPTIONAL,
  2020. PULONG Ulong OPTIONAL,
  2021. PLARGE_INTEGER LargeInteger OPTIONAL)
  2022. {
  2023. IO_STATUS_BLOCK IOSB;
  2024. AFD_INFO InfoData;
  2025. NTSTATUS Status;
  2026. HANDLE SockEvent;
  2027. Status = NtCreateEvent(&SockEvent,
  2028. GENERIC_READ | GENERIC_WRITE,
  2029. NULL,
  2030. 1,
  2031. FALSE);
  2032. if( !NT_SUCCESS(Status) )
  2033. return -1;
  2034. /* Set Info Class */
  2035. InfoData.InformationClass = AfdInformationClass;
  2036. /* Send IOCTL */
  2037. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  2038. SockEvent,
  2039. NULL,
  2040. NULL,
  2041. &IOSB,
  2042. IOCTL_AFD_GET_INFO,
  2043. &InfoData,
  2044. sizeof(InfoData),
  2045. &InfoData,
  2046. sizeof(InfoData));
  2047. /* Wait for return */
  2048. if (Status == STATUS_PENDING)
  2049. {
  2050. WaitForSingleObject(SockEvent, INFINITE);
  2051. Status = IOSB.Status;
  2052. }
  2053. if (Status != STATUS_SUCCESS)
  2054. return -1;
  2055. /* Return Information */
  2056. if (Ulong != NULL)
  2057. {
  2058. *Ulong = InfoData.Information.Ulong;
  2059. }
  2060. if (LargeInteger != NULL)
  2061. {
  2062. *LargeInteger = InfoData.Information.LargeInteger;
  2063. }
  2064. if (Boolean != NULL)
  2065. {
  2066. *Boolean = InfoData.Information.Boolean;
  2067. }
  2068. NtClose( SockEvent );
  2069. return 0;
  2070. }
  2071. int
  2072. SetSocketInformation(PSOCKET_INFORMATION Socket,
  2073. ULONG AfdInformationClass,
  2074. PBOOLEAN Boolean OPTIONAL,
  2075. PULONG Ulong OPTIONAL,
  2076. PLARGE_INTEGER LargeInteger OPTIONAL)
  2077. {
  2078. IO_STATUS_BLOCK IOSB;
  2079. AFD_INFO InfoData;
  2080. NTSTATUS Status;
  2081. HANDLE SockEvent;
  2082. Status = NtCreateEvent(&SockEvent,
  2083. GENERIC_READ | GENERIC_WRITE,
  2084. NULL,
  2085. 1,
  2086. FALSE);
  2087. if( !NT_SUCCESS(Status) )
  2088. return -1;
  2089. /* Set Info Class */
  2090. InfoData.InformationClass = AfdInformationClass;
  2091. /* Set Information */
  2092. if (Ulong != NULL)
  2093. {
  2094. InfoData.Information.Ulong = *Ulong;
  2095. }
  2096. if (LargeInteger != NULL)
  2097. {
  2098. InfoData.Information.LargeInteger = *LargeInteger;
  2099. }
  2100. if (Boolean != NULL)
  2101. {
  2102. InfoData.Information.Boolean = *Boolean;
  2103. }
  2104. /* Send IOCTL */
  2105. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  2106. SockEvent,
  2107. NULL,
  2108. NULL,
  2109. &IOSB,
  2110. IOCTL_AFD_SET_INFO,
  2111. &InfoData,
  2112. sizeof(InfoData),
  2113. NULL,
  2114. 0);
  2115. /* Wait for return */
  2116. if (Status == STATUS_PENDING)
  2117. {
  2118. WaitForSingleObject(SockEvent, INFINITE);
  2119. Status = IOSB.Status;
  2120. }
  2121. NtClose( SockEvent );
  2122. return Status == STATUS_SUCCESS ? 0 : -1;
  2123. }
  2124. PSOCKET_INFORMATION
  2125. GetSocketStructure(SOCKET Handle)
  2126. {
  2127. PSOCKET_INFORMATION CurrentSocket;
  2128. EnterCriticalSection(&SocketListLock);
  2129. CurrentSocket = SocketListHead;
  2130. while (CurrentSocket)
  2131. {
  2132. if (CurrentSocket->Handle == Handle)
  2133. {
  2134. LeaveCriticalSection(&SocketListLock);
  2135. return CurrentSocket;
  2136. }
  2137. CurrentSocket = CurrentSocket->NextSocket;
  2138. }
  2139. LeaveCriticalSection(&SocketListLock);
  2140. return NULL;
  2141. }
  2142. int CreateContext(PSOCKET_INFORMATION Socket)
  2143. {
  2144. IO_STATUS_BLOCK IOSB;
  2145. SOCKET_CONTEXT ContextData;
  2146. NTSTATUS Status;
  2147. HANDLE SockEvent;
  2148. Status = NtCreateEvent(&SockEvent,
  2149. GENERIC_READ | GENERIC_WRITE,
  2150. NULL,
  2151. 1,
  2152. FALSE);
  2153. if( !NT_SUCCESS(Status) )
  2154. return -1;
  2155. /* Create Context */
  2156. ContextData.SharedData = Socket->SharedData;
  2157. ContextData.SizeOfHelperData = 0;
  2158. RtlCopyMemory (&ContextData.LocalAddress,
  2159. Socket->LocalAddress,
  2160. Socket->SharedData.SizeOfLocalAddress);
  2161. RtlCopyMemory (&ContextData.RemoteAddress,
  2162. Socket->RemoteAddress,
  2163. Socket->SharedData.SizeOfRemoteAddress);
  2164. /* Send IOCTL */
  2165. Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
  2166. SockEvent,
  2167. NULL,
  2168. NULL,
  2169. &IOSB,
  2170. IOCTL_AFD_SET_CONTEXT,
  2171. &ContextData,
  2172. sizeof(ContextData),
  2173. NULL,
  2174. 0);
  2175. /* Wait for Completition */
  2176. if (Status == STATUS_PENDING)
  2177. {
  2178. WaitForSingleObject(SockEvent, INFINITE);
  2179. Status = IOSB.Status;
  2180. }
  2181. NtClose( SockEvent );
  2182. return Status == STATUS_SUCCESS ? 0 : -1;
  2183. }
  2184. BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
  2185. {
  2186. HANDLE hAsyncThread;
  2187. DWORD AsyncThreadId;
  2188. HANDLE AsyncEvent;
  2189. OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
  2190. NTSTATUS Status;
  2191. /* Check if the Thread Already Exists */
  2192. if (SockAsyncThreadRefCount)
  2193. {
  2194. ASSERT(SockAsyncCompletionPort);
  2195. return TRUE;
  2196. }
  2197. /* Create the Completion Port */
  2198. if (!SockAsyncCompletionPort)
  2199. {
  2200. Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
  2201. IO_COMPLETION_ALL_ACCESS,
  2202. NULL,
  2203. 2); // Allow 2 threads only
  2204. if (!NT_SUCCESS(Status))
  2205. {
  2206. AFD_DbgPrint(MID_TRACE,("Failed to create completion port\n"));
  2207. return FALSE;
  2208. }
  2209. /* Protect Handle */
  2210. HandleFlags.ProtectFromClose = TRUE;
  2211. HandleFlags.Inherit = FALSE;
  2212. Status = NtSetInformationObject(SockAsyncCompletionPort,
  2213. ObjectHandleFlagInformation,
  2214. &HandleFlags,
  2215. sizeof(HandleFlags));
  2216. }
  2217. /* Create the Async Event */
  2218. Status = NtCreateEvent(&AsyncEvent,
  2219. EVENT_ALL_ACCESS,
  2220. NULL,
  2221. NotificationEvent,
  2222. FALSE);
  2223. /* Create the Async Thread */
  2224. hAsyncThread = CreateThread(NULL,
  2225. 0,
  2226. (LPTHREAD_START_ROUTINE)SockAsyncThread,
  2227. NULL,
  2228. 0,
  2229. &AsyncThreadId);
  2230. /* Close the Handle */
  2231. NtClose(hAsyncThread);
  2232. /* Increase the Reference Count */
  2233. SockAsyncThreadRefCount++;
  2234. return TRUE;
  2235. }
  2236. int SockAsyncThread(PVOID ThreadParam)
  2237. {
  2238. PVOID AsyncContext;
  2239. PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
  2240. IO_STATUS_BLOCK IOSB;
  2241. NTSTATUS Status;
  2242. /* Make the Thread Higher Priority */
  2243. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  2244. /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
  2245. do
  2246. {
  2247. Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
  2248. (PVOID*)&AsyncCompletionRoutine,
  2249. &AsyncContext,
  2250. &IOSB,
  2251. NULL);
  2252. /* Call the Async Function */
  2253. if (NT_SUCCESS(Status))
  2254. {
  2255. (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
  2256. }
  2257. else
  2258. {
  2259. /* It Failed, sleep for a second */
  2260. Sleep(1000);
  2261. }
  2262. } while ((Status != STATUS_TIMEOUT));
  2263. /* The Thread has Ended */
  2264. return 0;
  2265. }
  2266. BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
  2267. {
  2268. UNICODE_STRING AfdHelper;
  2269. OBJECT_ATTRIBUTES ObjectAttributes;
  2270. IO_STATUS_BLOCK IoSb;
  2271. FILE_COMPLETION_INFORMATION CompletionInfo;
  2272. OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
  2273. /* First, make sure we're not already intialized */
  2274. if (SockAsyncHelperAfdHandle)
  2275. {
  2276. return TRUE;
  2277. }
  2278. /* Set up Handle Name and Object */
  2279. RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
  2280. InitializeObjectAttributes(&ObjectAttributes,
  2281. &AfdHelper,
  2282. OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
  2283. NULL,
  2284. NULL);
  2285. /* Open the Handle to AFD */
  2286. NtCreateFile(&SockAsyncHelperAfdHandle,
  2287. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  2288. &ObjectAttributes,
  2289. &IoSb,
  2290. NULL,
  2291. 0,
  2292. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2293. FILE_OPEN_IF,
  2294. 0,
  2295. NULL,
  2296. 0);
  2297. /*
  2298. * Now Set up the Completion Port Information
  2299. * This means that whenever a Poll is finished, the routine will be executed
  2300. */
  2301. CompletionInfo.Port = SockAsyncCompletionPort;
  2302. CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
  2303. NtSetInformationFile(SockAsyncHelperAfdHandle,
  2304. &IoSb,
  2305. &CompletionInfo,
  2306. sizeof(CompletionInfo),
  2307. FileCompletionInformation);
  2308. /* Protect the Handle */
  2309. HandleFlags.ProtectFromClose = TRUE;
  2310. HandleFlags.Inherit = FALSE;
  2311. NtSetInformationObject(SockAsyncCompletionPort,
  2312. ObjectHandleFlagInformation,
  2313. &HandleFlags,
  2314. sizeof(HandleFlags));
  2315. /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
  2316. SockAsyncSelectCalled = TRUE;
  2317. return TRUE;
  2318. }
  2319. VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
  2320. {
  2321. PASYNC_DATA AsyncData = Context;
  2322. PSOCKET_INFORMATION Socket;
  2323. ULONG x;
  2324. /* Get the Socket */
  2325. Socket = AsyncData->ParentSocket;
  2326. /* Check if the Sequence Number Changed behind our back */
  2327. if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
  2328. {
  2329. return;
  2330. }
  2331. /* Check we were manually called b/c of a failure */
  2332. if (!NT_SUCCESS(IoStatusBlock->Status))
  2333. {
  2334. /* FIXME: Perform Upcall */
  2335. return;
  2336. }
  2337. for (x = 1; x; x<<=1)
  2338. {
  2339. switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
  2340. {
  2341. case AFD_EVENT_RECEIVE:
  2342. if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
  2343. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
  2344. {
  2345. /* Make the Notifcation */
  2346. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2347. Socket->SharedData.wMsg,
  2348. Socket->Handle,
  2349. WSAMAKESELECTREPLY(FD_READ, 0));
  2350. /* Disable this event until the next read(); */
  2351. Socket->SharedData.AsyncDisabledEvents |= FD_READ;
  2352. }
  2353. break;
  2354. case AFD_EVENT_OOB_RECEIVE:
  2355. if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
  2356. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
  2357. {
  2358. /* Make the Notifcation */
  2359. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2360. Socket->SharedData.wMsg,
  2361. Socket->Handle,
  2362. WSAMAKESELECTREPLY(FD_OOB, 0));
  2363. /* Disable this event until the next read(); */
  2364. Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
  2365. }
  2366. break;
  2367. case AFD_EVENT_SEND:
  2368. if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
  2369. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
  2370. {
  2371. /* Make the Notifcation */
  2372. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2373. Socket->SharedData.wMsg,
  2374. Socket->Handle,
  2375. WSAMAKESELECTREPLY(FD_WRITE, 0));
  2376. /* Disable this event until the next write(); */
  2377. Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
  2378. }
  2379. break;
  2380. /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
  2381. case AFD_EVENT_CONNECT:
  2382. case AFD_EVENT_CONNECT_FAIL:
  2383. if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
  2384. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
  2385. {
  2386. /* Make the Notifcation */
  2387. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2388. Socket->SharedData.wMsg,
  2389. Socket->Handle,
  2390. WSAMAKESELECTREPLY(FD_CONNECT, 0));
  2391. /* Disable this event forever; */
  2392. Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
  2393. }
  2394. break;
  2395. case AFD_EVENT_ACCEPT:
  2396. if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
  2397. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
  2398. {
  2399. /* Make the Notifcation */
  2400. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2401. Socket->SharedData.wMsg,
  2402. Socket->Handle,
  2403. WSAMAKESELECTREPLY(FD_ACCEPT, 0));
  2404. /* Disable this event until the next accept(); */
  2405. Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
  2406. }
  2407. break;
  2408. case AFD_EVENT_DISCONNECT:
  2409. case AFD_EVENT_ABORT:
  2410. case AFD_EVENT_CLOSE:
  2411. if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
  2412. 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
  2413. {
  2414. /* Make the Notifcation */
  2415. (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
  2416. Socket->SharedData.wMsg,
  2417. Socket->Handle,
  2418. WSAMAKESELECTREPLY(FD_CLOSE, 0));
  2419. /* Disable this event forever; */
  2420. Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
  2421. }
  2422. break;
  2423. /* FIXME: Support QOS */
  2424. }
  2425. }
  2426. /* Check if there are any events left for us to check */
  2427. if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
  2428. {
  2429. return;
  2430. }
  2431. /* Keep Polling */
  2432. SockProcessAsyncSelect(Socket, AsyncData);
  2433. return;
  2434. }
  2435. VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
  2436. {
  2437. ULONG lNetworkEvents;
  2438. NTSTATUS Status;
  2439. /* Set up the Async Data Event Info */
  2440. AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
  2441. AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
  2442. AsyncData->AsyncSelectInfo.HandleCount = 1;
  2443. AsyncData->AsyncSelectInfo.Exclusive = TRUE;
  2444. AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
  2445. AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
  2446. /* Remove unwanted events */
  2447. lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
  2448. /* Set Events to wait for */
  2449. if (lNetworkEvents & FD_READ)
  2450. {
  2451. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
  2452. }
  2453. if (lNetworkEvents & FD_WRITE)
  2454. {
  2455. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
  2456. }
  2457. if (lNetworkEvents & FD_OOB)
  2458. {
  2459. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
  2460. }
  2461. if (lNetworkEvents & FD_ACCEPT)
  2462. {
  2463. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
  2464. }
  2465. /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
  2466. if (lNetworkEvents & FD_CONNECT)
  2467. {
  2468. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
  2469. }
  2470. if (lNetworkEvents & FD_CLOSE)
  2471. {
  2472. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
  2473. }
  2474. if (lNetworkEvents & FD_QOS)
  2475. {
  2476. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
  2477. }
  2478. if (lNetworkEvents & FD_GROUP_QOS)
  2479. {
  2480. AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
  2481. }
  2482. /* Send IOCTL */
  2483. Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
  2484. NULL,
  2485. NULL,
  2486. AsyncData,
  2487. &AsyncData->IoStatusBlock,
  2488. IOCTL_AFD_SELECT,
  2489. &AsyncData->AsyncSelectInfo,
  2490. sizeof(AsyncData->AsyncSelectInfo),
  2491. &AsyncData->AsyncSelectInfo,
  2492. sizeof(AsyncData->AsyncSelectInfo));
  2493. /* I/O Manager Won't call the completion routine, let's do it manually */
  2494. if (NT_SUCCESS(Status))
  2495. {
  2496. return;
  2497. }
  2498. else
  2499. {
  2500. AsyncData->IoStatusBlock.Status = Status;
  2501. SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
  2502. }
  2503. }
  2504. VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
  2505. {
  2506. PASYNC_DATA AsyncData = Context;
  2507. BOOL FreeContext = TRUE;
  2508. PSOCKET_INFORMATION Socket;
  2509. /* Get the Socket */
  2510. Socket = AsyncData->ParentSocket;
  2511. /* If someone closed it, stop the function */
  2512. if (Socket->SharedData.State != SocketClosed)
  2513. {
  2514. /* Check if the Sequence Number changed by now, in which case quit */
  2515. if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
  2516. {
  2517. /* Do the actuall select, if needed */
  2518. if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
  2519. {
  2520. SockProcessAsyncSelect(Socket, AsyncData);
  2521. FreeContext = FALSE;
  2522. }
  2523. }
  2524. }
  2525. /* Free the Context */
  2526. if (FreeContext)
  2527. {
  2528. HeapFree(GetProcessHeap(), 0, AsyncData);
  2529. }
  2530. return;
  2531. }
  2532. VOID
  2533. SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
  2534. IN ULONG Event)
  2535. {
  2536. PASYNC_DATA AsyncData;
  2537. /* Make sure the event is actually disabled */
  2538. if (!(Socket->SharedData.AsyncDisabledEvents & Event))
  2539. {
  2540. return;
  2541. }
  2542. /* Re-enable it */
  2543. Socket->SharedData.AsyncDisabledEvents &= ~Event;
  2544. /* Return if no more events are being polled */
  2545. if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
  2546. {
  2547. return;
  2548. }
  2549. /* Wait on new events */
  2550. AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
  2551. if (!AsyncData) return;
  2552. /* Create the Asynch Thread if Needed */
  2553. SockCreateOrReferenceAsyncThread();
  2554. /* Increase the sequence number to stop anything else */
  2555. Socket->SharedData.SequenceNumber++;
  2556. /* Set up the Async Data */
  2557. AsyncData->ParentSocket = Socket;
  2558. AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
  2559. /* Begin Async Select by using I/O Completion */
  2560. NtSetIoCompletion(SockAsyncCompletionPort,
  2561. (PVOID)&SockProcessQueuedAsyncSelect,
  2562. AsyncData,
  2563. 0,
  2564. 0);
  2565. /* All done */
  2566. return;
  2567. }
  2568. BOOL
  2569. WINAPI
  2570. DllMain(HANDLE hInstDll,
  2571. ULONG dwReason,
  2572. PVOID Reserved)
  2573. {
  2574. switch (dwReason)
  2575. {
  2576. case DLL_PROCESS_ATTACH:
  2577. AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n"));
  2578. /* Don't need thread attach notifications
  2579. so disable them to improve performance */
  2580. DisableThreadLibraryCalls(hInstDll);
  2581. /* List of DLL Helpers */
  2582. InitializeListHead(&SockHelpersListHead);
  2583. /* Heap to use when allocating */
  2584. GlobalHeap = GetProcessHeap();
  2585. /* Initialize the lock that protects our socket list */
  2586. InitializeCriticalSection(&SocketListLock);
  2587. AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
  2588. break;
  2589. case DLL_THREAD_ATTACH:
  2590. break;
  2591. case DLL_THREAD_DETACH:
  2592. break;
  2593. case DLL_PROCESS_DETACH:
  2594. /* Delete the socket list lock */
  2595. DeleteCriticalSection(&SocketListLock);
  2596. break;
  2597. }
  2598. AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n"));
  2599. return TRUE;
  2600. }
  2601. /* EOF */