Some work on winsock stack
[reactos.git] / reactos / drivers / net / afd / afd / opnclose.c
diff --git a/reactos/drivers/net/afd/afd/opnclose.c b/reactos/drivers/net/afd/afd/opnclose.c
new file mode 100644 (file)
index 0000000..c882531
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS Ancillary Function Driver
+ * FILE:        afd/opnclose.c
+ * PURPOSE:     File object creation and destruction
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISIONS:
+ *   CSH 01/09-2000 Created
+ */
+#include <afd.h>
+
+PAFDFCB AfdInitializeFCB(
+    PDEVICE_EXTENSION   DeviceExt,
+    PFILE_OBJECT        FileObject  OPTIONAL)
+/*
+ * FUNCTION: Allocates and initializes a File Control Block structure
+ */
+{
+    PAFDFCB NewFCB;
+
+    NewFCB = ExAllocatePool(NonPagedPool, sizeof(AFDFCB));
+    if (!NewFCB)
+        return NULL;
+
+    RtlZeroMemory(NewFCB, sizeof(AFDFCB));
+
+       ExInitializeResourceLite(&NewFCB->NTRequiredFCB.MainResource);
+       ExInitializeResourceLite(&NewFCB->NTRequiredFCB.PagingIoResource);
+
+       NewFCB->DeviceExt       = DeviceExt;
+       NewFCB->ReferenceCount  = 1;
+       NewFCB->OpenHandleCount = 1;
+
+    NewFCB->TdiAddressObjectHandle    = INVALID_HANDLE_VALUE;
+    NewFCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
+
+    InitializeListHead(&NewFCB->CCBListHead);
+
+    InsertTailList(&DeviceExt->FCBListHead, &NewFCB->ListEntry);
+
+       if (FileObject)
+               FileObject->FsContext = (PVOID)&NewFCB->NTRequiredFCB;
+
+    return NewFCB;
+}
+
+
+PAFDCCB AfdInitializeCCB(
+    PAFDFCB         FCB,
+    PFILE_OBJECT    FileObject)
+/*
+ * FUNCTION: Allocates and initializes a Context Control Block structure
+ */
+{
+    PAFDCCB NewCCB;
+
+    NewCCB = ExAllocatePool(NonPagedPool, sizeof(AFDCCB));
+    if (!NewCCB)
+        return NULL;
+
+    RtlZeroMemory(NewCCB, sizeof(AFDCCB));
+
+    NewCCB->FileObject = FileObject;
+
+    FileObject->FsContext2 = (PVOID)NewCCB;
+
+    InsertTailList(&FCB->CCBListHead, &NewCCB->ListEntry);
+
+    return NewCCB;
+}
+
+
+NTSTATUS AfdCreate(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+{
+    PAFD_SOCKET_INFORMATION SocketInfo;
+    PFILE_FULL_EA_INFORMATION EaInfo;
+    PDEVICE_EXTENSION DeviceExt;
+    PTA_ADDRESS Address;
+    NTSTATUS Status;
+    ULONG EaLength;
+    PAFDFCB FCB;
+    PAFDCCB CCB;
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    PFILE_OBJECT FileObject  = IrpSp->FileObject;
+
+    AFD_DbgPrint(MIN_TRACE, ("Called.\n"));
+
+    DeviceExt = DeviceObject->DeviceExtension;
+
+    EaInfo = Irp->AssociatedIrp.SystemBuffer;
+
+    /* Parameter check */
+    if (!EaInfo) {
+        AFD_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    SocketInfo = (PAFD_SOCKET_INFORMATION)(EaInfo->EaName + EaInfo->EaNameLength);
+
+    EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
+               EaInfo->EaNameLength +
+               EaInfo->EaValueLength;
+
+    if (EaLength < sizeof(FILE_FULL_EA_INFORMATION) +
+        AFD_SOCKET_LENGTH + sizeof(AFD_SOCKET_INFORMATION)) {
+        AFD_DbgPrint(MIN_TRACE, ("EA information has invalid length.\n"));
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    AFD_DbgPrint(MAX_TRACE, ("EaInfo at (0x%X)  length is (%d).\n", EaInfo, EaLength));
+
+    /* FIXME: File/socket could already be open, do a search for it */
+
+    FCB = AfdInitializeFCB(DeviceExt, FileObject);
+    CCB = AfdInitializeCCB(FCB, FileObject);
+    if (CCB && FCB) {
+        FCB->AddressFamily      = SocketInfo->AddressFamily;
+        FCB->SocketType         = SocketInfo->SocketType;
+        FCB->Protocol           = SocketInfo->Protocol;
+        FCB->HelperContext      = SocketInfo->HelperContext;
+        FCB->NotificationEvents = SocketInfo->NotificationEvents;
+        RtlCopyUnicodeString(&FCB->TdiDeviceName, &SocketInfo->TdiDeviceName);
+    } else {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    if (!NT_SUCCESS(Status)) {
+        /* FIXME: Cleanup */
+    }
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = 0;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    AFD_DbgPrint(MIN_TRACE, ("Leaving. Status (0x%X).\n", Status));
+
+    return Status;
+}
+
+
+NTSTATUS AfdClose(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
+{
+    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    PFILE_OBJECT FileObject  = IrpSp->FileObject;
+    NTSTATUS Status;
+    PAFDFCB FCB;
+    PAFDCCB CCB;
+
+    FCB = FileObject->FsContext;
+    CCB = FileObject->FsContext2;
+
+    AFD_DbgPrint(MIN_TRACE, ("Called.\n"));
+
+    switch (IrpSp->MajorFunction) {
+    /* Close a file object */
+    case IRP_MJ_CLOSE:
+        FCB->ReferenceCount--;
+        if (FCB->ReferenceCount < 1) {
+            /* Close TDI connection file object */
+            if (FCB->TdiConnectionObjectHandle != INVALID_HANDLE_VALUE) {
+                TdiCloseDevice(FCB->TdiConnectionObjectHandle, FCB->TdiConnectionObject);
+                FCB->TdiConnectionObjectHandle = INVALID_HANDLE_VALUE;
+            }
+
+            /* Close TDI address file object */
+            if (FCB->TdiAddressObjectHandle != INVALID_HANDLE_VALUE) {
+                AfdDeregisterEventHandlers(FCB);
+                TdiCloseDevice(FCB->TdiAddressObjectHandle, FCB->TdiAddressObject);
+                FCB->TdiAddressObjectHandle = INVALID_HANDLE_VALUE;
+            }
+
+            ExFreePool(FCB);
+        }
+
+        Status = STATUS_SUCCESS;
+        break;
+
+    /* Release resources bound to a file object */
+    case IRP_MJ_CLEANUP:
+        FCB->OpenHandleCount--;
+        Status = STATUS_SUCCESS;
+        break;
+
+       default:
+        Status = STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    ExFreePool(CCB);
+
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = 0;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return Status;
+}
+
+/* EOF */