- Implement a DispatchCleanup routine and properly separate cleanup from close
[reactos.git] / reactos / drivers / network / afd / afd / main.c
1 /* $Id$
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/main.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
7 * UPDATE HISTORY:
8 * 20040630 Created
9 *
10 * Suggestions: Uniform naming (AfdXxx)
11 */
12
13 /* INCLUDES */
14
15 #include "afd.h"
16 #include "tdi_proto.h"
17 #include "tdiconn.h"
18 #include "debug.h"
19
20 #ifdef DBG
21
22 /* See debug.h for debug/trace constants */
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel = 0;
25
26 #endif /* DBG */
27
28 void OskitDumpBuffer( PCHAR Data, UINT Len ) {
29 unsigned int i;
30
31 for( i = 0; i < Len; i++ ) {
32 if( i && !(i & 0xf) ) DbgPrint( "\n" );
33 if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
34 DbgPrint( " %02x", Data[i] & 0xff );
35 }
36 DbgPrint("\n");
37 }
38
39 /* FUNCTIONS */
40
41 NTSTATUS NTAPI
42 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
43
44 static NTSTATUS NTAPI
45 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
46 PIO_STACK_LOCATION IrpSp) {
47 PAFD_FCB FCB;
48 PFILE_OBJECT FileObject;
49 PAFD_DEVICE_EXTENSION DeviceExt;
50 PFILE_FULL_EA_INFORMATION EaInfo;
51 PAFD_CREATE_PACKET ConnectInfo = NULL;
52 ULONG EaLength;
53 PWCHAR EaInfoValue = NULL;
54 UINT Disposition, i;
55 NTSTATUS Status = STATUS_SUCCESS;
56
57 AFD_DbgPrint(MID_TRACE,
58 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
59
60 DeviceExt = DeviceObject->DeviceExtension;
61 FileObject = IrpSp->FileObject;
62 Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
63
64 Irp->IoStatus.Information = 0;
65
66 EaInfo = Irp->AssociatedIrp.SystemBuffer;
67
68 if( EaInfo ) {
69 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
70 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
71
72 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
73 EaInfo->EaNameLength +
74 EaInfo->EaValueLength;
75
76 AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
77 EaInfo, EaInfoValue));
78 }
79
80 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
81
82 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
83 if( FCB == NULL ) {
84 Irp->IoStatus.Status = STATUS_NO_MEMORY;
85 IoCompleteRequest(Irp, IO_NO_INCREMENT);
86 return STATUS_NO_MEMORY;
87 }
88
89 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
90
91 RtlZeroMemory( FCB, sizeof( *FCB ) );
92
93 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
94 FCB->State = SOCKET_STATE_CREATED;
95 FCB->FileObject = FileObject;
96 FCB->DeviceExt = DeviceExt;
97 FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
98 FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
99
100 KeInitializeSpinLock( &FCB->SpinLock );
101 ExInitializeFastMutex( &FCB->Mutex );
102 KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE );
103
104 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
105 InitializeListHead( &FCB->PendingIrpList[i] );
106 }
107
108 InitializeListHead( &FCB->DatagramList );
109 InitializeListHead( &FCB->PendingConnections );
110
111 AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
112
113 if( ConnectInfo ) {
114 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
115 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
116 FCB->TdiDeviceName.Buffer =
117 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
118
119 if( !FCB->TdiDeviceName.Buffer ) {
120 ExFreePool(FCB);
121 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
122 Irp->IoStatus.Status = STATUS_NO_MEMORY;
123 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
124 return STATUS_NO_MEMORY;
125 }
126
127 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
128 ConnectInfo->TransportName,
129 FCB->TdiDeviceName.Length );
130
131 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
132 EaInfo->EaName, &FCB->TdiDeviceName));
133 } else {
134 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
135 }
136
137 FileObject->FsContext = FCB;
138
139 /* It seems that UDP sockets are writable from inception */
140 if( FCB->Flags & SGID_CONNECTIONLESS ) {
141 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
142 /* Allocate our backup buffer */
143 FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
144 if( !FCB->Recv.Window ) Status = STATUS_NO_MEMORY;
145 if( NT_SUCCESS(Status) )
146 {
147 FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size );
148 if( !FCB->Send.Window ) {
149 if( FCB->Recv.Window ) ExFreePool( FCB->Recv.Window );
150 Status = STATUS_NO_MEMORY;
151 }
152 }
153 /* A datagram socket is always sendable */
154 FCB->PollState |= AFD_EVENT_SEND;
155 PollReeval( FCB->DeviceExt, FCB->FileObject );
156 }
157
158 if( !NT_SUCCESS(Status) ) {
159 if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
160 ExFreePool( FCB );
161 FileObject->FsContext = NULL;
162 }
163
164 Irp->IoStatus.Status = Status;
165 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
166
167 return Status;
168 }
169
170 VOID CleanupSocket( PAFD_FCB FCB ) {
171 UINT i;
172 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
173
174 AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", FCB));
175
176 if( !SocketAcquireStateLock( FCB ) ) return;
177
178 FCB->State = SOCKET_STATE_CLOSED;
179
180 InFlightRequest[0] = &FCB->ListenIrp;
181 InFlightRequest[1] = &FCB->ReceiveIrp;
182 InFlightRequest[2] = &FCB->SendIrp;
183 InFlightRequest[3] = &FCB->ConnectIrp;
184
185 /* Cancel our pending requests */
186 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
187 if( InFlightRequest[i]->InFlightRequest ) {
188 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
189 i, InFlightRequest[i]->InFlightRequest));
190 IoCancelIrp(InFlightRequest[i]->InFlightRequest);
191 }
192 }
193
194 FCB->State = SOCKET_STATE_CREATED;
195
196 if( FCB->EventSelect ) {
197 ObDereferenceObject( FCB->EventSelect );
198 FCB->EventSelect = NULL;
199 }
200 if( FCB->Context ) {
201 ExFreePool( FCB->Context );
202 FCB->Context = NULL;
203 }
204 if( FCB->Recv.Window ) {
205 ExFreePool( FCB->Recv.Window );
206 FCB->Recv.Window = NULL;
207 }
208 if( FCB->Send.Window ) {
209 ExFreePool( FCB->Send.Window );
210 FCB->Send.Window = NULL;
211 }
212 if( FCB->AddressFrom ) {
213 ExFreePool( FCB->AddressFrom );
214 FCB->AddressFrom = NULL;
215 }
216 if( FCB->LocalAddress ) {
217 ExFreePool( FCB->LocalAddress );
218 FCB->LocalAddress = NULL;
219 }
220 if( FCB->RemoteAddress ) {
221 ExFreePool( FCB->RemoteAddress );
222 FCB->RemoteAddress = NULL;
223 }
224 if( FCB->Connection.Object ) {
225 NtClose(FCB->Connection.Handle);
226 ObDereferenceObject(FCB->Connection.Object);
227 FCB->Connection.Object = NULL;
228 }
229 if( FCB->AddressFile.Object ) {
230 NtClose(FCB->AddressFile.Handle);
231 ObDereferenceObject(FCB->AddressFile.Object);
232 FCB->AddressFile.Object = NULL;
233 }
234
235 SocketStateUnlock( FCB );
236 }
237
238 VOID DestroySocket( PAFD_FCB FCB ) {
239 if( FCB->TdiDeviceName.Buffer )
240 ExFreePool(FCB->TdiDeviceName.Buffer);
241
242 ExFreePool(FCB);
243 AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));
244 }
245
246 static NTSTATUS NTAPI
247 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
248 PIO_STACK_LOCATION IrpSp)
249 {
250 PFILE_OBJECT FileObject = IrpSp->FileObject;
251 PAFD_FCB FCB = FileObject->FsContext;
252
253 AFD_DbgPrint(MID_TRACE,
254 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
255
256 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
257
258 AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
259
260 FileObject->FsContext = NULL;
261 SocketStateUnlock( FCB );
262
263 DestroySocket( FCB );
264
265 Irp->IoStatus.Status = STATUS_SUCCESS;
266 Irp->IoStatus.Information = 0;
267 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
268
269 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
270
271 return STATUS_SUCCESS;
272 }
273
274 static NTSTATUS NTAPI
275 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
276 PIO_STACK_LOCATION IrpSp)
277 {
278 PFILE_OBJECT FileObject = IrpSp->FileObject;
279 PAFD_FCB FCB = FileObject->FsContext;
280
281 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
282
283 CleanupSocket( FCB );
284
285 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
286
287 SocketStateUnlock( FCB );
288
289 Irp->IoStatus.Status = STATUS_SUCCESS;
290 Irp->IoStatus.Information = 0;
291 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
292
293 return STATUS_SUCCESS;
294 }
295
296 static NTSTATUS NTAPI
297 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
298 PIO_STACK_LOCATION IrpSp) {
299 PFILE_OBJECT FileObject = IrpSp->FileObject;
300 PAFD_FCB FCB = FileObject->FsContext;
301 PAFD_DISCONNECT_INFO DisReq;
302 IO_STATUS_BLOCK Iosb;
303 PTDI_CONNECTION_INFORMATION ConnInfo;
304 NTSTATUS Status;
305 USHORT Flags = 0;
306
307 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
308
309 if( !(DisReq = LockRequest( Irp, IrpSp )) )
310 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
311 Irp, 0 );
312
313 if (NULL == FCB->RemoteAddress)
314 {
315 ConnInfo = NULL;
316 }
317 else
318 {
319 Status = TdiBuildNullConnectionInfo
320 ( &ConnInfo, FCB->RemoteAddress->Address[0].AddressType );
321
322 if( !NT_SUCCESS(Status) || !ConnInfo )
323 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
324 Irp, 0 );
325 }
326
327 if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
328 Flags |= TDI_DISCONNECT_RELEASE;
329 if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
330 DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
331 Flags |= TDI_DISCONNECT_ABORT;
332
333 Status = TdiDisconnect( FCB->Connection.Object,
334 &DisReq->Timeout,
335 Flags,
336 &Iosb,
337 NULL,
338 NULL,
339 FCB->AddressFrom,
340 ConnInfo);
341
342 if (ConnInfo) ExFreePool( ConnInfo );
343
344 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
345 }
346
347 static NTSTATUS NTAPI
348 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
349 {
350 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
351 NTSTATUS Status = STATUS_SUCCESS;
352 #ifdef DBG
353 PFILE_OBJECT FileObject = IrpSp->FileObject;
354 #endif
355
356 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
357 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
358 AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
359 FileObject, IrpSp->FileObject));
360 ASSERT(FileObject == IrpSp->FileObject);
361 }
362
363 Irp->IoStatus.Information = 0;
364
365 switch(IrpSp->MajorFunction)
366 {
367 /* opening and closing handles to the device */
368 case IRP_MJ_CREATE:
369 /* Mostly borrowed from the named pipe file system */
370 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
371
372 case IRP_MJ_CLOSE:
373 /* Ditto the borrowing */
374 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
375
376 case IRP_MJ_CLEANUP:
377 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
378
379 /* write data */
380 case IRP_MJ_WRITE:
381 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
382
383 /* read data */
384 case IRP_MJ_READ:
385 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
386
387 case IRP_MJ_DEVICE_CONTROL:
388 {
389 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
390 case IOCTL_AFD_BIND:
391 return AfdBindSocket( DeviceObject, Irp, IrpSp );
392
393 case IOCTL_AFD_CONNECT:
394 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
395
396 case IOCTL_AFD_START_LISTEN:
397 return AfdListenSocket( DeviceObject, Irp, IrpSp );
398
399 case IOCTL_AFD_RECV:
400 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
401 FALSE );
402
403 case IOCTL_AFD_SELECT:
404 return AfdSelect( DeviceObject, Irp, IrpSp );
405
406 case IOCTL_AFD_EVENT_SELECT:
407 return AfdEventSelect( DeviceObject, Irp, IrpSp );
408
409 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
410 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
411
412 case IOCTL_AFD_RECV_DATAGRAM:
413 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
414
415 case IOCTL_AFD_SEND:
416 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
417 FALSE );
418
419 case IOCTL_AFD_SEND_DATAGRAM:
420 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
421
422 case IOCTL_AFD_GET_INFO:
423 return AfdGetInfo( DeviceObject, Irp, IrpSp );
424
425 case IOCTL_AFD_GET_CONTEXT:
426 return AfdGetContext( DeviceObject, Irp, IrpSp );
427
428 case IOCTL_AFD_SET_CONTEXT:
429 return AfdSetContext( DeviceObject, Irp, IrpSp );
430
431 case IOCTL_AFD_WAIT_FOR_LISTEN:
432 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
433
434 case IOCTL_AFD_ACCEPT:
435 return AfdAccept( DeviceObject, Irp, IrpSp );
436
437 case IOCTL_AFD_DISCONNECT:
438 return AfdDisconnect( DeviceObject, Irp, IrpSp );
439
440 case IOCTL_AFD_GET_SOCK_NAME:
441 return AfdGetSockName( DeviceObject, Irp, IrpSp );
442
443 case IOCTL_AFD_GET_PEER_NAME:
444 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
445
446 case IOCTL_AFD_GET_TDI_HANDLES:
447 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
448 break;
449
450 case IOCTL_AFD_SET_INFO:
451 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_INFO\n"));
452 break;
453
454 case IOCTL_AFD_SET_CONNECT_DATA:
455 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
456 break;
457
458 case IOCTL_AFD_SET_CONNECT_OPTIONS:
459 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
460 break;
461
462 case IOCTL_AFD_SET_DISCONNECT_DATA:
463 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
464 break;
465
466 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
467 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
468 break;
469
470 case IOCTL_AFD_GET_CONNECT_DATA:
471 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
472 break;
473
474 case IOCTL_AFD_GET_CONNECT_OPTIONS:
475 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
476 break;
477
478 case IOCTL_AFD_GET_DISCONNECT_DATA:
479 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
480 break;
481
482 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
483 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
484 break;
485
486 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
487 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
488 break;
489
490 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
491 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
492 break;
493
494 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
495 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
496 break;
497
498 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
499 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
500 break;
501
502 case IOCTL_AFD_DEFER_ACCEPT:
503 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_DEFER_ACCEPT\n"));
504 break;
505
506 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
507 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
508 break;
509
510 default:
511 Status = STATUS_NOT_IMPLEMENTED;
512 AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
513 IrpSp->Parameters.DeviceIoControl.
514 IoControlCode));
515 break;
516 }
517 break;
518 }
519
520 /* unsupported operations */
521 default:
522 {
523 Status = STATUS_NOT_IMPLEMENTED;
524 AFD_DbgPrint(MIN_TRACE,
525 ("Irp: Unknown Major code was %x\n",
526 IrpSp->MajorFunction));
527 break;
528 }
529 }
530
531 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
532 Irp->IoStatus.Status = Status;
533 IoCompleteRequest(Irp, IO_NO_INCREMENT);
534
535 return (Status);
536 }
537
538 static VOID NTAPI
539 AfdUnload(PDRIVER_OBJECT DriverObject)
540 {
541 }
542
543 NTSTATUS NTAPI
544 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
545 {
546 PDEVICE_OBJECT DeviceObject;
547 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
548 PAFD_DEVICE_EXTENSION DeviceExt;
549 NTSTATUS Status;
550
551 /* register driver routines */
552 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
553 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
554 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
555 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
556 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
557 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
558 DriverObject->DriverUnload = AfdUnload;
559
560 Status = IoCreateDevice
561 ( DriverObject,
562 sizeof(AFD_DEVICE_EXTENSION),
563 &wstrDeviceName,
564 FILE_DEVICE_NAMED_PIPE,
565 0,
566 FALSE,
567 &DeviceObject );
568
569 /* failure */
570 if(!NT_SUCCESS(Status))
571 {
572 return (Status);
573 }
574
575 DeviceExt = DeviceObject->DeviceExtension;
576 KeInitializeSpinLock( &DeviceExt->Lock );
577 InitializeListHead( &DeviceExt->Polls );
578
579 AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
580 DeviceObject, DeviceExt));
581
582 return (Status);
583 }
584
585 /* EOF */