📄 create.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/fs/np/create.c
* PURPOSE: Named pipe filesystem
* PROGRAMMER: David Welch <welch@cwcom.net>
*/
/* INCLUDES ******************************************************************/
#include "npfs.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
static PNPFS_FCB
NpfsFindPipe(PNPFS_DEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PipeName)
{
PLIST_ENTRY CurrentEntry;
PNPFS_FCB Fcb;
CurrentEntry = DeviceExt->PipeListHead.Flink;
while (CurrentEntry != &DeviceExt->PipeListHead)
{
Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
if (RtlCompareUnicodeString(PipeName,
&Fcb->PipeName,
TRUE) == 0)
{
DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
return Fcb;
}
CurrentEntry = CurrentEntry->Flink;
}
return NULL;
}
static PNPFS_CCB
NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
{
PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter;
KIRQL oldIrql;
PIRP Irp;
CurrentEntry = Fcb->WaiterListHead.Flink;
while (CurrentEntry != &Fcb->WaiterListHead)
{
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
if (Waiter->Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
{
DPRINT("Server found! CCB %p\n", Waiter->Ccb);
IoAcquireCancelSpinLock(&oldIrql);
if (!Irp->Cancel)
{
(void)IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(oldIrql);
return Waiter->Ccb;
}
IoReleaseCancelSpinLock(oldIrql);
}
CurrentEntry = CurrentEntry->Flink;
}
return NULL;
}
static VOID
NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
PNPFS_CCB Ccb)
{
PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter;
PIRP Irp;
CurrentEntry = Fcb->WaiterListHead.Flink;
while (CurrentEntry != &Fcb->WaiterListHead)
{
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
if (Waiter->Ccb == Ccb)
{
DPRINT("Server found! CCB %p\n", Waiter->Ccb);
RemoveEntryList(&Waiter->Entry);
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
CurrentEntry = CurrentEntry->Flink;
}
}
NTSTATUS STDCALL
NpfsCreate(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PNPFS_FCB Fcb;
PNPFS_CCB ClientCcb;
PNPFS_CCB ServerCcb = NULL;
PNPFS_DEVICE_EXTENSION DeviceExt;
BOOLEAN SpecialAccess;
ACCESS_MASK DesiredAccess;
DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
DPRINT("FileObject %p\n", FileObject);
DPRINT("FileName %wZ\n", &FileObject->FileName);
Irp->IoStatus.Information = 0;
SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
if (SpecialAccess)
{
DPRINT("NpfsCreate() open client end for special use!\n");
}
/*
* Step 1. Find the pipe we're trying to open.
*/
KeLockMutex(&DeviceExt->PipeListLock);
Fcb = NpfsFindPipe(DeviceExt,
&FileObject->FileName);
if (Fcb == NULL)
{
/* Not found, bail out with error. */
DPRINT("No pipe found!\n");
KeUnlockMutex(&DeviceExt->PipeListLock);
Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_OBJECT_NAME_NOT_FOUND;
}
KeUnlockMutex(&DeviceExt->PipeListLock);
/*
* Acquire the lock for CCB lists. From now on no modifications to the
* CCB lists are allowed, because it can cause various misconsistencies.
*/
KeLockMutex(&Fcb->CcbListLock);
/*
* Step 2. Create the client CCB.
*/
ClientCcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
if (ClientCcb == NULL)
{
DPRINT("No memory!\n");
KeUnlockMutex(&Fcb->CcbListLock);
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
ClientCcb->Fcb = Fcb;
ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
ClientCcb->OtherSide = NULL;
ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
InitializeListHead(&ClientCcb->ReadRequestListHead);
DPRINT("CCB: %p\n", ClientCcb);
/* Initialize data list. */
if (Fcb->OutboundQuota)
{
ClientCcb->Data = ExAllocatePool(PagedPool, Fcb->OutboundQuota);
if (ClientCcb->Data == NULL)
{
DPRINT("No memory!\n");
ExFreePool(ClientCcb);
KeUnlockMutex(&Fcb->CcbListLock);
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
}
else
{
ClientCcb->Data = NULL;
}
ClientCcb->ReadPtr = ClientCcb->Data;
ClientCcb->WritePtr = ClientCcb->Data;
ClientCcb->ReadDataAvailable = 0;
ClientCcb->WriteQuotaAvailable = Fcb->OutboundQuota;
ClientCcb->MaxDataLength = Fcb->OutboundQuota;
ExInitializeFastMutex(&ClientCcb->DataListLock);
KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientCcb->ReadEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientCcb->WriteEvent, SynchronizationEvent, FALSE);
/*
* Step 3. Search for listening server CCB.
*/
if (!SpecialAccess)
{
/*
* WARNING: Point of no return! Once we get the server CCB it's
* possible that we completed a wait request and so we have to
* complete even this request.
*/
ServerCcb = NpfsFindListeningServerInstance(Fcb);
if (ServerCcb == NULL)
{
PLIST_ENTRY CurrentEntry;
PNPFS_CCB Ccb;
/*
* If no waiting server CCB was found then try to pick
* one of the listing server CCB on the pipe.
*/
CurrentEntry = Fcb->ServerCcbListHead.Flink;
while (CurrentEntry != &Fcb->ServerCcbListHead)
{
Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
{
ServerCcb = Ccb;
break;
}
CurrentEntry = CurrentEntry->Flink;
}
/*
* No one is listening to me?! I'm so lonely... :(
*/
if (ServerCcb == NULL)
{
/* Not found, bail out with error for FILE_OPEN requests. */
DPRINT("No listening server CCB found!\n");
if (ClientCcb->Data)
ExFreePool(ClientCcb->Data);
KeUnlockMutex(&Fcb->CcbListLock);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
}
else
{
/* Signal the server thread and remove it from the waiter list */
/* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
}
}
else if (IsListEmpty(&Fcb->ServerCcbListHead))
{
DPRINT("No server fcb found!\n");
KeUnlockMutex(&Fcb->CcbListLock);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* Step 4. Add the client CCB to a list and connect it if possible.
*/
/* Add the client CCB to the pipe CCB list. */
InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry);
/* Connect to listening server side */
if (ServerCcb)
{
ClientCcb->OtherSide = ServerCcb;
ServerCcb->OtherSide = ClientCcb;
ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
}
KeUnlockMutex(&Fcb->CcbListLock);
FileObject->FsContext = Fcb;
FileObject->FsContext2 = ClientCcb;
FileObject->Flags |= FO_NAMED_PIPE;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT("Success!\n");
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PNPFS_DEVICE_EXTENSION DeviceExt;
PNPFS_FCB Fcb;
PNPFS_CCB Ccb;
PNAMED_PIPE_CREATE_PARAMETERS Buffer;
BOOLEAN NewPipe = FALSE;
DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
DPRINT("FileObject %p\n", FileObject);
DPRINT("Pipe name %wZ\n", &FileObject->FileName);
Buffer = IoStack->Parameters.CreatePipe.Parameters;
Irp->IoStatus.Information = 0;
if (!(IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
(IoStack->Parameters.CreatePipe.ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
Ccb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
if (Ccb == NULL)
{
Irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
KeLockMutex(&DeviceExt->PipeListLock);
/*
* First search for existing Pipe with the same name.
*/
Fcb = NpfsFindPipe(DeviceExt,
&FileObject->FileName);
if (Fcb != NULL)
{
/*
* Found Pipe with the same name. Check if we are
* allowed to use it.
*/
KeUnlockMutex(&DeviceExt->PipeListLock);
if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
{
DPRINT("Out of instances.\n");
ExFreePool(Ccb);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
/* FIXME: Check pipe modes also! */
if (Fcb->MaximumInstances != Buffer->MaximumInstances ||
Fcb->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart)
{
DPRINT("Asked for invalid pipe mode.\n");
ExFreePool(Ccb);
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -