:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / net / afd / afd / opnclose.c
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS Ancillary Function Driver
4  * FILE:        afd/opnclose.c
5  * PURPOSE:     File object creation and destruction
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  *   CSH 01/09-2000 Created
9  */
10 #include <afd.h>
11
12 PAFDFCB AfdInitializeFCB(
13     PDEVICE_EXTENSION   DeviceExt,
14     PFILE_OBJECT        FileObject  OPTIONAL)
15 /*
16  * FUNCTION: Allocates and initializes a File Control Block structure
17  */
18 {
19   PAFDFCB NewFCB;
20
21   NewFCB = ExAllocatePool(NonPagedPool, sizeof(AFDFCB));
22   if (!NewFCB)
23     return NULL;
24
25   RtlZeroMemory(NewFCB, sizeof(AFDFCB));
26
27         ExInitializeResourceLite(&NewFCB->NTRequiredFCB.MainResource);
28         ExInitializeResourceLite(&NewFCB->NTRequiredFCB.PagingIoResource);
29
30         NewFCB->DeviceExt       = DeviceExt;
31         NewFCB->ReferenceCount  = 1;
32         NewFCB->OpenHandleCount = 1;
33
34   NewFCB->TdiAddressObjectHandle    = INVALID_HANDLE_VALUE;
35   NewFCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
36
37   InitializeListHead(&NewFCB->CCBListHead);
38
39   InsertTailList(&DeviceExt->FCBListHead, &NewFCB->ListEntry);
40
41   InitializeListHead(&NewFCB->ReceiveQueue);
42   KeInitializeSpinLock(&NewFCB->ReceiveQueueLock);
43
44   InitializeListHead(&NewFCB->ReadRequestQueue);
45   KeInitializeSpinLock(&NewFCB->ReadRequestQueueLock);
46
47         if (FileObject)
48                 FileObject->FsContext = (PVOID)NewFCB;
49
50   AFD_DbgPrint(MAX_TRACE, ("FCB created for file object (0x%X) at (0x%X).\n", FileObject, NewFCB));
51
52   return NewFCB;
53 }
54
55
56 PAFDCCB AfdInitializeCCB(
57     PAFDFCB         FCB,
58     PFILE_OBJECT    FileObject)
59 /*
60  * FUNCTION: Allocates and initializes a Context Control Block structure
61  */
62 {
63     PAFDCCB NewCCB;
64
65     NewCCB = ExAllocatePool(NonPagedPool, sizeof(AFDCCB));
66     if (!NewCCB)
67         return NULL;
68
69     RtlZeroMemory(NewCCB, sizeof(AFDCCB));
70
71     NewCCB->FileObject = FileObject;
72
73     FileObject->FsContext2 = (PVOID)NewCCB;
74
75     InsertTailList(&FCB->CCBListHead, &NewCCB->ListEntry);
76
77     AFD_DbgPrint(MAX_TRACE, ("CCB created for file object (0x%X) at (0x%X).\n", FileObject, NewCCB));
78
79     return NewCCB;
80 }
81
82
83 NTSTATUS
84 STDCALL
85 AfdCreate(
86     PDEVICE_OBJECT DeviceObject,
87     PIRP Irp)
88 {
89     PAFD_SOCKET_INFORMATION SocketInfo;
90     PFILE_FULL_EA_INFORMATION EaInfo;
91     PDEVICE_EXTENSION DeviceExt;
92     PTA_ADDRESS Address;
93     NTSTATUS Status;
94     ULONG EaLength;
95     PAFDFCB FCB;
96     PAFDCCB CCB;
97     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
98     PFILE_OBJECT FileObject  = IrpSp->FileObject;
99
100     AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
101
102     assert(DeviceObject);
103
104     DeviceExt = DeviceObject->DeviceExtension;
105
106     EaInfo = Irp->AssociatedIrp.SystemBuffer;
107
108     /* Parameter check */
109     if (!EaInfo) {
110         AFD_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
111         return STATUS_INVALID_PARAMETER;
112     }
113
114     SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + EaInfo->EaNameLength);
115
116     EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
117                EaInfo->EaNameLength +
118                EaInfo->EaValueLength;
119
120     if (EaLength < sizeof(FILE_FULL_EA_INFORMATION) +
121         AFD_SOCKET_LENGTH + sizeof(AFD_SOCKET_INFORMATION)) {
122         AFD_DbgPrint(MIN_TRACE, ("EA information has invalid length.\n"));
123         return STATUS_INVALID_PARAMETER;
124     }
125
126     AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X)  length is (%d).\n", EaInfo, EaLength));
127
128     /* FIXME: File/socket could already be open, do a search for it */
129
130     FCB = AfdInitializeFCB(DeviceExt, FileObject);
131
132     CCB = AfdInitializeCCB(FCB, FileObject);
133
134     if (CCB && FCB) {
135         FCB->CommandChannel = SocketInfo->CommandChannel;
136
137         if (!FCB->CommandChannel) {
138             FCB->AddressFamily      = SocketInfo->AddressFamily;
139             FCB->SocketType         = SocketInfo->SocketType;
140             FCB->Protocol           = SocketInfo->Protocol;
141             FCB->SocketName         = SocketInfo->Name;
142             FCB->HelperContext      = SocketInfo->HelperContext;
143             FCB->NotificationEvents = SocketInfo->NotificationEvents;
144
145             if (RtlCreateUnicodeString(&FCB->TdiDeviceName, SocketInfo->TdiDeviceName.Buffer)) {
146
147                 RtlCopyUnicodeString(&FCB->TdiDeviceName, &SocketInfo->TdiDeviceName);
148
149                 AFD_DbgPrint(MAX_TRACE, ("TDI device name is (%wZ).\n", &FCB->TdiDeviceName));
150
151                 /* Open address file now for raw sockets */
152                 if (FCB->SocketType == SOCK_RAW) {
153                     AFD_DbgPrint(MAX_TRACE, ("Opening raw socket.\n"));
154
155                     Status = TdiOpenAddressFile(
156                         &FCB->TdiDeviceName,
157                         &SocketInfo->Name,
158                         &FCB->TdiAddressObjectHandle,
159                         &FCB->TdiAddressObject);
160                     if (NT_SUCCESS(Status)) {
161                         Status = AfdRegisterEventHandlers(FCB);
162                         if (NT_SUCCESS(Status)) {
163                           FCB->State = SOCKET_STATE_BOUND;
164                         } else {
165                           AFD_DbgPrint(MAX_TRACE, ("AfdRegisterEventHandlers() failed (0x%X).\n", Status));
166                         }
167                     } else {
168                       AFD_DbgPrint(MAX_TRACE, ("TdiOpenAddressFile() failed (0x%X).\n", Status));
169                     }
170                 } else
171                     Status = STATUS_SUCCESS;
172             } else
173                 Status = STATUS_INSUFFICIENT_RESOURCES;
174         } else
175             Status = STATUS_SUCCESS;
176     } else
177         Status = STATUS_INSUFFICIENT_RESOURCES;
178
179     if (!NT_SUCCESS(Status)) {
180       /* FIXME: Cleanup */
181       AFD_DbgPrint(MAX_TRACE, ("FIXME: Cleanup.\n"));
182     }
183
184     Irp->IoStatus.Status = Status;
185     Irp->IoStatus.Information = 0;
186
187     IoCompleteRequest(Irp, IO_NO_INCREMENT);
188
189     AFD_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
190
191     return Status;
192 }
193
194
195 NTSTATUS
196 STDCALL
197 AfdClose(
198     PDEVICE_OBJECT DeviceObject,
199     PIRP Irp)
200 {
201     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
202     PFILE_OBJECT FileObject  = IrpSp->FileObject;
203     NTSTATUS Status;
204     PAFDFCB FCB;
205     PAFDCCB CCB;
206
207     AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
208
209     assert(DeviceObject);
210     assert(FileObject);
211
212     FCB = FileObject->FsContext;
213     CCB = FileObject->FsContext2;
214
215     switch (IrpSp->MajorFunction) {
216     /* Close a file object */
217     case IRP_MJ_CLOSE:
218         FCB->ReferenceCount--;
219         if (FCB->ReferenceCount < 1) {
220             if (!FCB->CommandChannel) {
221                 /* Close TDI connection file object */
222                 if (FCB->TdiConnectionObjectHandle != INVALID_HANDLE_VALUE) {
223                     TdiCloseDevice(FCB->TdiConnectionObjectHandle, FCB->TdiConnectionObject);
224                     FCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
225                 }
226
227                 /* Close TDI address file object */
228                 if (FCB->TdiAddressObjectHandle != INVALID_HANDLE_VALUE) {
229                     AfdDeregisterEventHandlers(FCB);
230                     TdiCloseDevice(FCB->TdiAddressObjectHandle, FCB->TdiAddressObject);
231                     FCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
232                 }
233             }
234
235             ExFreePool(FCB);
236         }
237
238         Status = STATUS_SUCCESS;
239         break;
240
241     /* Release resources bound to a file object */
242     case IRP_MJ_CLEANUP:
243         FCB->OpenHandleCount--;
244         Status = STATUS_SUCCESS;
245         break;
246
247         default:
248         Status = STATUS_INVALID_DEVICE_REQUEST;
249     }
250
251     ExFreePool(CCB);
252
253     Irp->IoStatus.Status = Status;
254     Irp->IoStatus.Information = 0;
255
256     AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", Irp));
257
258     IoCompleteRequest(Irp, IO_NO_INCREMENT);
259
260     return Status;
261 }
262
263 /* EOF */