mirror of
https://github.com/reactos/reactos.git
synced 2024-12-19 00:53:33 +08:00
335 lines
9.1 KiB
C
335 lines
9.1 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: drivers/filesystems/msfs/create.c
|
|
* PURPOSE: Mailslot filesystem
|
|
* PROGRAMMER: Eric Kohl
|
|
* Nikita Pechenkin (n.pechenkin@mail.ru)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "msfs.h"
|
|
|
|
#include <ndk/iotypes.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/* Creates the client side */
|
|
NTSTATUS DEFAULTAPI
|
|
MsfsCreate(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PFILE_OBJECT FileObject;
|
|
PMSFS_DEVICE_EXTENSION DeviceExtension;
|
|
PMSFS_FCB Fcb;
|
|
PMSFS_CCB Ccb;
|
|
PMSFS_FCB current = NULL;
|
|
PLIST_ENTRY current_entry;
|
|
KIRQL oldIrql;
|
|
|
|
DPRINT("MsfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
FileObject = IoStack->FileObject;
|
|
|
|
DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
|
|
|
|
Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_CCB), 'cFsM');
|
|
if (Ccb == NULL)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
KeLockMutex(&DeviceExtension->FcbListLock);
|
|
current_entry = DeviceExtension->FcbListHead.Flink;
|
|
while (current_entry != &DeviceExtension->FcbListHead)
|
|
{
|
|
current = CONTAINING_RECORD(current_entry,
|
|
MSFS_FCB,
|
|
FcbListEntry);
|
|
|
|
if (!RtlCompareUnicodeString(&FileObject->FileName, ¤t->Name, TRUE))
|
|
break;
|
|
|
|
current_entry = current_entry->Flink;
|
|
}
|
|
|
|
if (current_entry == &DeviceExtension->FcbListHead)
|
|
{
|
|
ExFreePoolWithTag(Ccb, 'cFsM');
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
Fcb = current;
|
|
|
|
KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
|
|
InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
|
|
KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
|
|
|
|
Fcb->ReferenceCount++;
|
|
|
|
Ccb->Fcb = Fcb;
|
|
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
FileObject->FsContext = Fcb;
|
|
FileObject->FsContext2 = Ccb;
|
|
FileObject->Flags |= FO_MAILSLOT;
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
/* Creates the server side */
|
|
NTSTATUS DEFAULTAPI
|
|
MsfsCreateMailslot(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PFILE_OBJECT FileObject;
|
|
PMSFS_DEVICE_EXTENSION DeviceExtension;
|
|
PMSFS_FCB Fcb;
|
|
PMSFS_CCB Ccb;
|
|
KIRQL oldIrql;
|
|
PLIST_ENTRY current_entry;
|
|
PMSFS_FCB current = NULL;
|
|
PMAILSLOT_CREATE_PARAMETERS Buffer;
|
|
|
|
DPRINT("MsfsCreateMailslot(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
FileObject = IoStack->FileObject;
|
|
Buffer = IoStack->Parameters.CreateMailslot.Parameters;
|
|
|
|
DPRINT("Mailslot name: %wZ\n", &FileObject->FileName);
|
|
|
|
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_FCB), 'fFsM');
|
|
if (Fcb == NULL)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Fcb->Name.Length = FileObject->FileName.Length;
|
|
Fcb->Name.MaximumLength = Fcb->Name.Length + sizeof(UNICODE_NULL);
|
|
Fcb->Name.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
|
Fcb->Name.MaximumLength,
|
|
'NFsM');
|
|
if (Fcb->Name.Buffer == NULL)
|
|
{
|
|
ExFreePoolWithTag(Fcb, 'fFsM');
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
RtlCopyUnicodeString(&Fcb->Name, &FileObject->FileName);
|
|
|
|
Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(MSFS_CCB), 'cFsM');
|
|
if (Ccb == NULL)
|
|
{
|
|
ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
|
|
ExFreePoolWithTag(Fcb, 'fFsM');
|
|
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Fcb->ReferenceCount = 0;
|
|
InitializeListHead(&Fcb->CcbListHead);
|
|
KeInitializeSpinLock(&Fcb->CcbListLock);
|
|
|
|
Fcb->MaxMessageSize = Buffer->MaximumMessageSize;
|
|
Fcb->MessageCount = 0;
|
|
Fcb->TimeOut = Buffer->ReadTimeout;
|
|
|
|
InitializeListHead(&Fcb->MessageListHead);
|
|
KeInitializeSpinLock(&Fcb->MessageListLock);
|
|
|
|
KeInitializeSpinLock(&Fcb->QueueLock);
|
|
InitializeListHead(&Fcb->PendingIrpQueue);
|
|
IoCsqInitialize(&Fcb->CancelSafeQueue,
|
|
MsfsInsertIrp,
|
|
MsfsRemoveIrp,
|
|
MsfsPeekNextIrp,
|
|
MsfsAcquireLock,
|
|
MsfsReleaseLock,
|
|
MsfsCompleteCanceledIrp);
|
|
|
|
KeLockMutex(&DeviceExtension->FcbListLock);
|
|
current_entry = DeviceExtension->FcbListHead.Flink;
|
|
while (current_entry != &DeviceExtension->FcbListHead)
|
|
{
|
|
current = CONTAINING_RECORD(current_entry,
|
|
MSFS_FCB,
|
|
FcbListEntry);
|
|
|
|
if (!RtlCompareUnicodeString(&Fcb->Name, ¤t->Name, TRUE))
|
|
break;
|
|
|
|
current_entry = current_entry->Flink;
|
|
}
|
|
|
|
if (current_entry != &DeviceExtension->FcbListHead)
|
|
{
|
|
ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
|
|
ExFreePoolWithTag(Fcb, 'fFsM');
|
|
ExFreePoolWithTag(Ccb, 'cFsM');
|
|
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
InsertTailList(&DeviceExtension->FcbListHead,
|
|
&Fcb->FcbListEntry);
|
|
}
|
|
|
|
KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
|
|
InsertTailList(&Fcb->CcbListHead, &Ccb->CcbListEntry);
|
|
KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
|
|
|
|
Fcb->ReferenceCount++;
|
|
Fcb->ServerCcb = Ccb;
|
|
Ccb->Fcb = Fcb;
|
|
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
FileObject->FsContext = Fcb;
|
|
FileObject->FsContext2 = Ccb;
|
|
FileObject->Flags |= FO_MAILSLOT;
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS DEFAULTAPI
|
|
MsfsClose(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IoStack;
|
|
PFILE_OBJECT FileObject;
|
|
PMSFS_DEVICE_EXTENSION DeviceExtension;
|
|
PMSFS_FCB Fcb;
|
|
PMSFS_CCB Ccb;
|
|
PMSFS_MESSAGE Message;
|
|
KIRQL oldIrql;
|
|
|
|
DPRINT("MsfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
FileObject = IoStack->FileObject;
|
|
|
|
KeLockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
if (DeviceExtension->FcbListHead.Flink == &DeviceExtension->FcbListHead)
|
|
{
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Fcb = FileObject->FsContext;
|
|
Ccb = FileObject->FsContext2;
|
|
|
|
DPRINT("Mailslot name: %wZ\n", &Fcb->Name);
|
|
|
|
Fcb->ReferenceCount--;
|
|
if (Fcb->ServerCcb == Ccb)
|
|
{
|
|
/* delete all messages from message-list */
|
|
KeAcquireSpinLock(&Fcb->MessageListLock, &oldIrql);
|
|
|
|
while (Fcb->MessageListHead.Flink != &Fcb->MessageListHead)
|
|
{
|
|
Message = CONTAINING_RECORD(Fcb->MessageListHead.Flink,
|
|
MSFS_MESSAGE,
|
|
MessageListEntry);
|
|
RemoveEntryList(Fcb->MessageListHead.Flink);
|
|
ExFreePoolWithTag(Message, 'rFsM');
|
|
}
|
|
|
|
Fcb->MessageCount = 0;
|
|
|
|
KeReleaseSpinLock(&Fcb->MessageListLock, oldIrql);
|
|
Fcb->ServerCcb = NULL;
|
|
}
|
|
|
|
KeAcquireSpinLock(&Fcb->CcbListLock, &oldIrql);
|
|
RemoveEntryList(&Ccb->CcbListEntry);
|
|
KeReleaseSpinLock(&Fcb->CcbListLock, oldIrql);
|
|
ExFreePoolWithTag(Ccb, 'cFsM');
|
|
FileObject->FsContext2 = NULL;
|
|
|
|
if (Fcb->ReferenceCount == 0)
|
|
{
|
|
DPRINT("ReferenceCount == 0: Deleting mailslot data\n");
|
|
RemoveEntryList(&Fcb->FcbListEntry);
|
|
ExFreePoolWithTag(Fcb->Name.Buffer, 'NFsM');
|
|
ExFreePoolWithTag(Fcb, 'fFsM');
|
|
}
|
|
|
|
KeUnlockMutex(&DeviceExtension->FcbListLock);
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* EOF */
|