ReactOS 0.4.15-dev-7953-g1f49173
AfdHelpers.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Utility function definitions for calling AFD
5 * COPYRIGHT: Copyright 2015-2018 Thomas Faber (thomas.faber@reactos.org)
6 * Copyright 2019 Pierre Schweitzer (pierre@reactos.org)
7 */
8
9#include "precomp.h"
10
11#define DD_UDP_DEVICE_NAME L"\\Device\\Udp"
12
13typedef struct _AFD_CREATE_PACKET_NT6 {
22
25 _Out_ PHANDLE SocketHandle,
27 _In_ int SocketType,
28 _In_ int Protocol)
29{
35 PAFD_CREATE_PACKET AfdPacket;
36 PAFD_CREATE_PACKET_NT6 AfdPacket6;
37 ULONG SizeOfPacket;
41 UNICODE_STRING TransportName = SocketType == SOCK_STREAM ? TcpTransportName : UdpTransportName;
42 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd\\Endpoint");
43
44 *SocketHandle = NULL;
45
46 if (LOBYTE(LOWORD(GetVersion())) >= 6)
47 {
48 SizeOfPacket = FIELD_OFFSET(AFD_CREATE_PACKET_NT6, TransportName) + TransportName.Length + sizeof(UNICODE_NULL);
49 }
50 else
51 {
52 SizeOfPacket = FIELD_OFFSET(AFD_CREATE_PACKET, TransportName) + TransportName.Length + sizeof(UNICODE_NULL);
53 }
54 EaLength = SizeOfPacket + FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) + EaName.Length + sizeof(ANSI_NULL);
55
56 /* Set up EA Buffer */
57 EaBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, EaLength);
58 if (!EaBuffer)
59 {
61 }
62
63 EaBuffer->NextEntryOffset = 0;
64 EaBuffer->Flags = 0;
65 EaBuffer->EaNameLength = EaName.Length;
66 RtlCopyMemory(EaBuffer->EaName,
67 EaName.Buffer,
68 EaName.Length + sizeof(ANSI_NULL));
69 EaBuffer->EaValueLength = SizeOfPacket;
70
71 if (LOBYTE(LOWORD(GetVersion())) >= 6)
72 {
73 AfdPacket6 = (PAFD_CREATE_PACKET_NT6)(EaBuffer->EaName + EaBuffer->EaNameLength + sizeof(ANSI_NULL));
74 AfdPacket6->GroupID = 0;
76 {
78 }
79 else if (SocketType == SOCK_STREAM)
80 {
82 }
83 AfdPacket6->AddressFamily = AddressFamily;
84 AfdPacket6->SocketType = SocketType;
85 AfdPacket6->Protocol = Protocol;
86 AfdPacket6->SizeOfTransportName = TransportName.Length;
87 RtlCopyMemory(AfdPacket6->TransportName,
88 TransportName.Buffer,
89 TransportName.Length + sizeof(UNICODE_NULL));
90 }
91 else
92 {
93 AfdPacket = (PAFD_CREATE_PACKET)(EaBuffer->EaName + EaBuffer->EaNameLength + sizeof(ANSI_NULL));
94 AfdPacket->GroupID = 0;
96 {
98 }
99 else if (SocketType == SOCK_STREAM)
100 {
102 }
103 AfdPacket->SizeOfTransportName = TransportName.Length;
104 RtlCopyMemory(AfdPacket->TransportName,
105 TransportName.Buffer,
106 TransportName.Length + sizeof(UNICODE_NULL));
107 }
108
110 &DeviceName,
112 0,
113 0);
114
115 Status = NtCreateFile(SocketHandle,
118 &IoStatus,
119 NULL,
120 0,
123 0,
124 EaBuffer,
125 EaLength);
126
127 RtlFreeHeap(RtlGetProcessHeap(), 0, EaBuffer);
128
129 return Status;
130}
131
132
135 _In_ HANDLE SocketHandle,
136 _In_ const struct sockaddr *Address,
137 _In_ ULONG AddressLength)
138{
141 PAFD_BIND_DATA BindInfo;
142 ULONG BindInfoLength;
144
147 NULL,
149 FALSE);
150 if (!NT_SUCCESS(Status))
151 {
152 return Status;
153 }
154
155 BindInfoLength = FIELD_OFFSET(AFD_BIND_DATA, Address.Address[0].Address) +
156 AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
157 BindInfo = RtlAllocateHeap(RtlGetProcessHeap(),
158 0,
159 BindInfoLength);
160 if (!BindInfo)
161 {
162 NtClose(Event);
164 }
165
166 BindInfo->ShareType = AFD_SHARE_UNIQUE;
167 BindInfo->Address.TAAddressCount = 1;
168 BindInfo->Address.Address[0].AddressType = Address->sa_family;
169 BindInfo->Address.Address[0].AddressLength = AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
170 RtlCopyMemory(&BindInfo->Address.Address[0].Address,
171 Address->sa_data,
172 BindInfo->Address.Address[0].AddressLength);
173
174 Status = NtDeviceIoControlFile(SocketHandle,
175 Event,
176 NULL,
177 NULL,
178 &IoStatus,
180 BindInfo,
181 BindInfoLength,
182 BindInfo,
183 BindInfoLength);
184 if (Status == STATUS_PENDING)
185 {
187 Status = IoStatus.Status;
188 }
189
190 RtlFreeHeap(RtlGetProcessHeap(), 0, BindInfo);
191 NtClose(Event);
192
193 return Status;
194}
195
198 _In_ HANDLE SocketHandle,
199 _In_ const struct sockaddr *Address,
200 _In_ ULONG AddressLength)
201{
204 PAFD_CONNECT_INFO ConnectInfo;
205 ULONG ConnectInfoLength;
207
210 NULL,
212 FALSE);
213 if (!NT_SUCCESS(Status))
214 {
215 return Status;
216 }
217
218 ASSERT(FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress.Address[0].Address) == 20);
219 ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress.Address[0].Address) +
220 AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
221 ConnectInfo = RtlAllocateHeap(RtlGetProcessHeap(),
222 0,
223 ConnectInfoLength);
224 if (!ConnectInfo)
225 {
226 NtClose(Event);
228 }
229
230
231 ConnectInfo->UseSAN = FALSE;
232 ConnectInfo->Root = 0;
233 ConnectInfo->Unknown = 0;
234 ConnectInfo->RemoteAddress.TAAddressCount = 1;
235 ConnectInfo->RemoteAddress.Address[0].AddressType = Address->sa_family;
236 ConnectInfo->RemoteAddress.Address[0].AddressLength = AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
238 Address->sa_data,
239 ConnectInfo->RemoteAddress.Address[0].AddressLength);
240
241 Status = NtDeviceIoControlFile(SocketHandle,
242 Event,
243 NULL,
244 NULL,
245 &IoStatus,
247 ConnectInfo,
248 ConnectInfoLength,
249 NULL,
250 0);
251 if (Status == STATUS_PENDING)
252 {
254 Status = IoStatus.Status;
255 }
256
257 RtlFreeHeap(RtlGetProcessHeap(), 0, ConnectInfo);
258 NtClose(Event);
259
260 return Status;
261}
262
265 _In_ HANDLE SocketHandle,
266 _In_ const void *Buffer,
268{
271 AFD_SEND_INFO SendInfo;
273 AFD_WSABUF AfdBuffer;
274
277 NULL,
279 FALSE);
280 if (!NT_SUCCESS(Status))
281 {
282 return Status;
283 }
284
285 AfdBuffer.buf = (PVOID)Buffer;
286 AfdBuffer.len = BufferLength;
287 SendInfo.BufferArray = &AfdBuffer;
288 SendInfo.BufferCount = 1;
289 SendInfo.TdiFlags = 0;
290 SendInfo.AfdFlags = 0;
291
292 Status = NtDeviceIoControlFile(SocketHandle,
293 Event,
294 NULL,
295 NULL,
296 &IoStatus,
298 &SendInfo,
299 sizeof(SendInfo),
300 NULL,
301 0);
302 if (Status == STATUS_PENDING)
303 {
305 Status = IoStatus.Status;
306 }
307
308 NtClose(Event);
309
310 return Status;
311}
312
315 _In_ HANDLE SocketHandle,
316 _In_ const void *Buffer,
318 _In_ const struct sockaddr *Address,
319 _In_ ULONG AddressLength)
320{
323 AFD_SEND_INFO_UDP SendInfo;
325 AFD_WSABUF AfdBuffer;
326 PTRANSPORT_ADDRESS TransportAddress;
327 ULONG TransportAddressLength;
328
331 NULL,
333 FALSE);
334 if (!NT_SUCCESS(Status))
335 {
336 return Status;
337 }
338
339 TransportAddressLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address[0].Address) +
340 AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
341 TransportAddress = RtlAllocateHeap(RtlGetProcessHeap(),
342 0,
343 TransportAddressLength);
344 if (!TransportAddress)
345 {
346 NtClose(Event);
348 }
349 TransportAddress->TAAddressCount = 1;
350 TransportAddress->Address[0].AddressType = Address->sa_family;
351 TransportAddress->Address[0].AddressLength = AddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
352 RtlCopyMemory(&TransportAddress->Address[0].Address,
353 Address->sa_data,
354 TransportAddress->Address[0].AddressLength);
355
356 AfdBuffer.buf = (PVOID)Buffer;
357 AfdBuffer.len = BufferLength;
358 RtlZeroMemory(&SendInfo, sizeof(SendInfo));
359 SendInfo.BufferArray = &AfdBuffer;
360 SendInfo.BufferCount = 1;
361 SendInfo.AfdFlags = 0;
362 SendInfo.TdiConnection.RemoteAddress = TransportAddress;
363 SendInfo.TdiConnection.RemoteAddressLength = TransportAddressLength;
364
365 Status = NtDeviceIoControlFile(SocketHandle,
366 Event,
367 NULL,
368 NULL,
369 &IoStatus,
371 &SendInfo,
372 sizeof(SendInfo),
373 NULL,
374 0);
375 if (Status == STATUS_PENDING)
376 {
378 Status = IoStatus.Status;
379 }
380
381 RtlFreeHeap(RtlGetProcessHeap(), 0, TransportAddress);
382 NtClose(Event);
383
384 return Status;
385}
386
389 _In_ HANDLE SocketHandle,
391 _In_opt_ PBOOLEAN Boolean,
393 _In_opt_ PLARGE_INTEGER LargeInteger)
394{
397 AFD_INFO InfoData;
399
402 NULL,
404 FALSE);
405 if (!NT_SUCCESS(Status))
406 {
407 return Status;
408 }
409
411
412 if (Ulong != NULL)
413 {
414 InfoData.Information.Ulong = *Ulong;
415 }
416 if (LargeInteger != NULL)
417 {
418 InfoData.Information.LargeInteger = *LargeInteger;
419 }
420 if (Boolean != NULL)
421 {
422 InfoData.Information.Boolean = *Boolean;
423 }
424
425 Status = NtDeviceIoControlFile(SocketHandle,
426 Event,
427 NULL,
428 NULL,
429 &IoStatus,
431 &InfoData,
432 sizeof(InfoData),
433 NULL,
434 0);
435 if (Status == STATUS_PENDING)
436 {
438 Status = IoStatus.Status;
439 }
440
441 NtClose(Event);
442
443 return Status;
444}
445
448 _In_ HANDLE SocketHandle,
450 _In_opt_ PBOOLEAN Boolean,
452 _In_opt_ PLARGE_INTEGER LargeInteger)
453{
456 AFD_INFO InfoData;
458
461 NULL,
463 FALSE);
464 if (!NT_SUCCESS(Status))
465 {
466 return Status;
467 }
468
470
471 Status = NtDeviceIoControlFile(SocketHandle,
472 Event,
473 NULL,
474 NULL,
475 &IoStatus,
477 &InfoData,
478 sizeof(InfoData),
479 &InfoData,
480 sizeof(InfoData));
481 if (Status == STATUS_PENDING)
482 {
484 Status = IoStatus.Status;
485 }
486
487 NtClose(Event);
488
489 if (Status != STATUS_SUCCESS)
490 {
491 return Status;
492 }
493
494 if (Ulong != NULL)
495 {
496 *Ulong = InfoData.Information.Ulong;
497 }
498 if (LargeInteger != NULL)
499 {
500 *LargeInteger = InfoData.Information.LargeInteger;
501 }
502 if (Boolean != NULL)
503 {
504 *Boolean = InfoData.Information.Boolean;
505 }
506
507 return Status;
508}
struct _AFD_CREATE_PACKET_NT6 AFD_CREATE_PACKET_NT6
NTSTATUS AfdGetInformation(_In_ HANDLE SocketHandle, _In_ ULONG InformationClass, _In_opt_ PBOOLEAN Boolean, _In_opt_ PULONG Ulong, _In_opt_ PLARGE_INTEGER LargeInteger)
Definition: AfdHelpers.c:447
NTSTATUS AfdBind(_In_ HANDLE SocketHandle, _In_ const struct sockaddr *Address, _In_ ULONG AddressLength)
Definition: AfdHelpers.c:134
struct _AFD_CREATE_PACKET_NT6 * PAFD_CREATE_PACKET_NT6
NTSTATUS AfdSendTo(_In_ HANDLE SocketHandle, _In_ const void *Buffer, _In_ ULONG BufferLength, _In_ const struct sockaddr *Address, _In_ ULONG AddressLength)
Definition: AfdHelpers.c:314
NTSTATUS AfdSend(_In_ HANDLE SocketHandle, _In_ const void *Buffer, _In_ ULONG BufferLength)
Definition: AfdHelpers.c:264
NTSTATUS AfdSetInformation(_In_ HANDLE SocketHandle, _In_ ULONG InformationClass, _In_opt_ PBOOLEAN Boolean, _In_opt_ PULONG Ulong, _In_opt_ PLARGE_INTEGER LargeInteger)
Definition: AfdHelpers.c:388
NTSTATUS AfdCreateSocket(_Out_ PHANDLE SocketHandle, _In_ int AddressFamily, _In_ int SocketType, _In_ int Protocol)
Definition: AfdHelpers.c:24
#define DD_UDP_DEVICE_NAME
Definition: AfdHelpers.c:11
NTSTATUS AfdConnect(_In_ HANDLE SocketHandle, _In_ const struct sockaddr *Address, _In_ ULONG AddressLength)
Definition: AfdHelpers.c:197
LONG NTSTATUS
Definition: precomp.h:26
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define SOCK_STREAM
Definition: tcpip.h:118
IN PVCB IN PDIRENT OUT PULONG EaLength
Definition: fatprocs.h:878
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ FILTER_INFORMATION_CLASS InformationClass
Definition: fltkernel.h:1713
#define FILE_OPEN_IF
Definition: from_kernel.h:56
Status
Definition: gdiplustypes.h:25
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_INHERIT
Definition: winternl.h:225
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define LOBYTE(W)
Definition: jmemdos.c:487
#define ASSERT(a)
Definition: mode.c:44
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
IN PCO_ADDRESS_FAMILY AddressFamily
Definition: ndis.h:1906
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define GENERIC_WRITE
Definition: nt_native.h:90
#define UNICODE_NULL
#define ANSI_NULL
@ NotificationEvent
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_PENDING
Definition: ntstatus.h:82
#define L(x)
Definition: ntvdm.h:50
#define LOWORD(l)
Definition: pedump.c:82
static WCHAR Address[46]
Definition: ping.c:68
DWORD WINAPI GetVersion()
Definition: redirtest.c:5
struct _AFD_CREATE_PACKET * PAFD_CREATE_PACKET
#define IOCTL_AFD_SET_INFO
Definition: shared.h:295
#define AfdCommand
Definition: shared.h:12
#define IOCTL_AFD_GET_INFO
Definition: shared.h:327
#define IOCTL_AFD_CONNECT
Definition: shared.h:269
#define IOCTL_AFD_BIND
Definition: shared.h:267
#define AFD_SHARE_UNIQUE
Definition: shared.h:191
#define AFD_ENDPOINT_MESSAGE_ORIENTED
Definition: shared.h:154
#define IOCTL_AFD_SEND_DATAGRAM
Definition: shared.h:283
#define IOCTL_AFD_SEND
Definition: shared.h:281
#define AFD_ENDPOINT_CONNECTIONLESS
Definition: shared.h:153
#define STATUS_SUCCESS
Definition: shellext.h:65
ULONG ShareType
Definition: shared.h:39
TRANSPORT_ADDRESS Address
Definition: shared.h:40
TRANSPORT_ADDRESS RemoteAddress
Definition: shared.h:121
BOOLEAN UseSAN
Definition: shared.h:118
DWORD EndpointFlags
Definition: shared.h:22
WCHAR TransportName[1]
Definition: shared.h:25
DWORD SizeOfTransportName
Definition: shared.h:24
ULONG InformationClass
Definition: shared.h:29
ULONG Ulong
Definition: shared.h:31
union _AFD_INFO::@3386 Information
BOOLEAN Boolean
Definition: shared.h:33
LARGE_INTEGER LargeInteger
Definition: shared.h:32
ULONG BufferCount
Definition: shared.h:109
TDI_CONNECTION_INFORMATION TdiConnection
Definition: shared.h:112
PAFD_WSABUF BufferArray
Definition: shared.h:108
ULONG BufferCount
Definition: shared.h:102
PAFD_WSABUF BufferArray
Definition: shared.h:101
ULONG TdiFlags
Definition: shared.h:104
ULONG AfdFlags
Definition: shared.h:103
PCHAR buf
Definition: shared.h:18
UINT len
Definition: shared.h:17
UCHAR Address[1]
Definition: tdi.h:340
USHORT AddressLength
Definition: tdi.h:338
USHORT AddressType
Definition: tdi.h:339
TA_ADDRESS Address[1]
Definition: tdi.h:377
LONG TAAddressCount
Definition: tdi.h:376
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
unsigned long Ulong
Definition: utypes.h:42
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
#define SOCK_DGRAM
Definition: winsock.h:336
#define DD_TCP_DEVICE_NAME
Definition: wshtcpip.h:27
_In_ USHORT SocketType
Definition: wsk.h:182
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:172
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ ULONG _In_ ULONG _In_ ULONG _In_opt_ PVOID EaBuffer
Definition: iofuncs.h:845
__wchar_t WCHAR
Definition: xmlstorage.h:180