mirror of
https://github.com/reactos/reactos.git
synced 2024-08-14 23:49:49 +00:00
368 lines
9.7 KiB
C
368 lines
9.7 KiB
C
/*
|
|
* PROJECT: ReactOS Named Pipe FileSystem
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
* FILE: drivers/filesystems/npfs/strucsup.c
|
|
* PURPOSE:
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include "npfs.h"
|
|
|
|
// File ID number for NPFS bugchecking support
|
|
#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_STRUCSUP)
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
WCHAR NpRootDCBName[] = L"\\";
|
|
PNP_VCB NpVcb;
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
RTL_GENERIC_COMPARE_RESULTS
|
|
NTAPI
|
|
NpEventTableCompareRoutine(IN PRTL_GENERIC_TABLE Table,
|
|
IN PVOID FirstStruct,
|
|
IN PVOID SecondStruct)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return GenericEqual;
|
|
}
|
|
|
|
PVOID
|
|
NTAPI
|
|
NpEventTableAllocate(IN PRTL_GENERIC_TABLE Table,
|
|
IN CLONG ByteSize)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NpEventTableDeallocate(IN PRTL_GENERIC_TABLE Table,
|
|
IN PVOID Buffer)
|
|
{
|
|
UNIMPLEMENTED;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
|
|
IN PVOID Buffer)
|
|
{
|
|
if (!Buffer) return FALSE;
|
|
|
|
ObDereferenceObject(((PNP_EVENT_BUFFER)Buffer)->Event);
|
|
return RtlDeleteElementGenericTable(Table, Buffer);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NpDeleteFcb(IN PNP_FCB Fcb,
|
|
IN PLIST_ENTRY ListEntry)
|
|
{
|
|
PNP_DCB Dcb;
|
|
PAGED_CODE();
|
|
|
|
Dcb = Fcb->ParentDcb;
|
|
if (Fcb->CurrentInstances) NpBugCheck(0, 0, 0);
|
|
|
|
NpCancelWaiter(&NpVcb->WaitQueue,
|
|
&Fcb->FullName,
|
|
STATUS_OBJECT_NAME_NOT_FOUND,
|
|
ListEntry);
|
|
|
|
RemoveEntryList(&Fcb->DcbEntry);
|
|
|
|
if (Fcb->SecurityDescriptor)
|
|
{
|
|
ObDereferenceSecurityDescriptor(Fcb->SecurityDescriptor, 1);
|
|
}
|
|
|
|
RtlRemoveUnicodePrefix(&NpVcb->PrefixTable, &Fcb->PrefixTableEntry);
|
|
ExFreePool(Fcb->FullName.Buffer);
|
|
ExFreePool(Fcb);
|
|
NpCheckForNotify(Dcb, TRUE, ListEntry);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NpDeleteCcb(IN PNP_CCB Ccb,
|
|
IN PLIST_ENTRY ListEntry)
|
|
{
|
|
PNP_ROOT_DCB_FCB RootDcbCcb;
|
|
PAGED_CODE();
|
|
|
|
RootDcbCcb = (PNP_ROOT_DCB_FCB)Ccb;
|
|
if (Ccb->NodeType == NPFS_NTC_CCB)
|
|
{
|
|
RemoveEntryList(&Ccb->CcbEntry);
|
|
--Ccb->Fcb->CurrentInstances;
|
|
|
|
NpDeleteEventTableEntry(&NpVcb->EventTable,
|
|
Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END]);
|
|
NpDeleteEventTableEntry(&NpVcb->EventTable,
|
|
Ccb->NonPagedCcb->EventBuffer[FILE_PIPE_SERVER_END]);
|
|
NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]);
|
|
NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND]);
|
|
NpCheckForNotify(Ccb->Fcb->ParentDcb, FALSE, ListEntry);
|
|
ExDeleteResourceLite(&Ccb->NonPagedCcb->Lock);
|
|
NpUninitializeSecurity(Ccb);
|
|
if (Ccb->ClientSession)
|
|
{
|
|
ExFreePool(Ccb->ClientSession);
|
|
Ccb->ClientSession = NULL;
|
|
}
|
|
ExFreePool(Ccb->NonPagedCcb);
|
|
}
|
|
else if (RootDcbCcb->NodeType == NPFS_NTC_ROOT_DCB_CCB && RootDcbCcb->Unknown)
|
|
{
|
|
ExFreePool(RootDcbCcb->Unknown);
|
|
}
|
|
|
|
ExFreePool(Ccb);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NpInitializeVcb(VOID)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
RtlZeroMemory(NpVcb, sizeof(*NpVcb));
|
|
|
|
NpVcb->NodeType = NPFS_NTC_VCB;
|
|
RtlInitializeUnicodePrefix(&NpVcb->PrefixTable);
|
|
ExInitializeResourceLite(&NpVcb->Lock);
|
|
RtlInitializeGenericTable(&NpVcb->EventTable,
|
|
NpEventTableCompareRoutine,
|
|
NpEventTableAllocate,
|
|
NpEventTableDeallocate,
|
|
0);
|
|
NpInitializeWaitQueue(&NpVcb->WaitQueue);
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB *NewRootCcb)
|
|
{
|
|
PNP_ROOT_DCB_FCB RootCcb;
|
|
PAGED_CODE();
|
|
|
|
RootCcb = ExAllocatePoolWithTag(PagedPool, sizeof(*RootCcb), NPFS_ROOT_DCB_CCB_TAG);
|
|
if (!RootCcb) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlZeroMemory(RootCcb, sizeof(*RootCcb));
|
|
RootCcb->NodeType = NPFS_NTC_ROOT_DCB_CCB;
|
|
*NewRootCcb = RootCcb;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpCreateRootDcb(VOID)
|
|
{
|
|
PNP_DCB Dcb;
|
|
PAGED_CODE();
|
|
|
|
if (NpVcb->RootDcb)
|
|
{
|
|
NpBugCheck(0, 0, 0);
|
|
}
|
|
|
|
NpVcb->RootDcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Dcb), NPFS_DCB_TAG);
|
|
if (!NpVcb->RootDcb)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Dcb = NpVcb->RootDcb;
|
|
RtlZeroMemory(Dcb, sizeof(*Dcb));
|
|
Dcb->NodeType = NPFS_NTC_ROOT_DCB;
|
|
|
|
InitializeListHead(&Dcb->DcbEntry);
|
|
InitializeListHead(&Dcb->NotifyList);
|
|
InitializeListHead(&Dcb->NotifyList2);
|
|
InitializeListHead(&Dcb->FcbList);
|
|
|
|
Dcb->FullName.Buffer = NpRootDCBName;
|
|
Dcb->FullName.Length = sizeof(NpRootDCBName) - sizeof(UNICODE_NULL);
|
|
Dcb->FullName.MaximumLength = sizeof(NpRootDCBName);
|
|
|
|
Dcb->ShortName.Length = Dcb->FullName.Length;
|
|
Dcb->ShortName.MaximumLength = Dcb->FullName.MaximumLength;
|
|
Dcb->ShortName.Buffer = Dcb->FullName.Buffer;
|
|
|
|
if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
|
|
&Dcb->FullName,
|
|
&Dcb->PrefixTableEntry))
|
|
{
|
|
NpBugCheck(0, 0, 0);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpCreateFcb(IN PNP_DCB Dcb,
|
|
IN PUNICODE_STRING PipeName,
|
|
IN ULONG MaximumInstances,
|
|
IN LARGE_INTEGER Timeout,
|
|
IN USHORT NamedPipeConfiguration,
|
|
IN USHORT NamedPipeType,
|
|
OUT PNP_FCB *NewFcb)
|
|
{
|
|
PNP_FCB Fcb;
|
|
BOOLEAN RootPipe;
|
|
PWCHAR NameBuffer;
|
|
USHORT Length, MaximumLength;
|
|
PAGED_CODE();
|
|
|
|
Length = PipeName->Length;
|
|
MaximumLength = Length + sizeof(UNICODE_NULL);
|
|
|
|
if ((Length < sizeof(WCHAR)) || (MaximumLength < Length))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
RootPipe = FALSE;
|
|
if (PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
|
|
{
|
|
Length += sizeof(OBJ_NAME_PATH_SEPARATOR);
|
|
MaximumLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
|
|
RootPipe = TRUE;
|
|
if (MaximumLength < sizeof(WCHAR))
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
Fcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Fcb), NPFS_FCB_TAG);
|
|
if (!Fcb) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlZeroMemory(Fcb, sizeof(*Fcb));
|
|
Fcb->MaximumInstances = MaximumInstances;
|
|
Fcb->Timeout = Timeout;
|
|
Fcb->NodeType = NPFS_NTC_FCB;
|
|
Fcb->ParentDcb = Dcb;
|
|
InitializeListHead(&Fcb->CcbList);
|
|
|
|
NameBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
MaximumLength,
|
|
NPFS_NAME_BLOCK_TAG);
|
|
if (!NameBuffer)
|
|
{
|
|
ExFreePool(Fcb);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
InsertTailList(&Dcb->FcbList, &Fcb->DcbEntry);
|
|
|
|
if (RootPipe)
|
|
{
|
|
NameBuffer[0] = OBJ_NAME_PATH_SEPARATOR;
|
|
RtlCopyMemory(NameBuffer + 1,
|
|
PipeName->Buffer,
|
|
PipeName->Length);
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory(NameBuffer,
|
|
PipeName->Buffer,
|
|
PipeName->Length);
|
|
}
|
|
|
|
NameBuffer[Length / sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
Fcb->FullName.Length = Length;
|
|
Fcb->FullName.MaximumLength = MaximumLength;
|
|
Fcb->FullName.Buffer = NameBuffer;
|
|
|
|
Fcb->ShortName.MaximumLength = Length;
|
|
Fcb->ShortName.Length = Length - sizeof(OBJ_NAME_PATH_SEPARATOR);
|
|
Fcb->ShortName.Buffer = NameBuffer + 1;
|
|
|
|
if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
|
|
&Fcb->FullName,
|
|
&Fcb->PrefixTableEntry))
|
|
{
|
|
NpBugCheck(0, 0, 0);
|
|
}
|
|
|
|
Fcb->NamedPipeConfiguration = NamedPipeConfiguration;
|
|
Fcb->NamedPipeType = NamedPipeType;
|
|
*NewFcb = Fcb;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
NpCreateCcb(IN PNP_FCB Fcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN UCHAR State,
|
|
IN UCHAR ReadMode,
|
|
IN UCHAR CompletionMode,
|
|
IN ULONG InQuota,
|
|
IN ULONG OutQuota,
|
|
OUT PNP_CCB *NewCcb)
|
|
{
|
|
PNP_CCB Ccb;
|
|
PNP_NONPAGED_CCB CcbNonPaged;
|
|
NTSTATUS Status;
|
|
PAGED_CODE();
|
|
|
|
Ccb = ExAllocatePoolWithTag(PagedPool, sizeof(*Ccb), NPFS_CCB_TAG);
|
|
if (!Ccb) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
CcbNonPaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(*CcbNonPaged), NPFS_CCB_TAG);
|
|
if (!CcbNonPaged)
|
|
{
|
|
ExFreePool(Ccb);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(CcbNonPaged, sizeof(*CcbNonPaged));
|
|
CcbNonPaged->NodeType = NPFS_NTC_NONPAGED_CCB;
|
|
|
|
RtlZeroMemory(Ccb, sizeof(*Ccb));
|
|
Ccb->NodeType = NPFS_NTC_CCB;
|
|
Ccb->NonPagedCcb = CcbNonPaged;
|
|
Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
|
|
Ccb->Fcb = Fcb;
|
|
Ccb->NamedPipeState = State;
|
|
Ccb->ReadMode[FILE_PIPE_SERVER_END] = ReadMode;
|
|
Ccb->CompletionMode[FILE_PIPE_SERVER_END] = CompletionMode;
|
|
|
|
Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND], InQuota);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ExFreePool(CcbNonPaged);
|
|
ExFreePool(Ccb);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = NpInitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], OutQuota);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NpUninitializeDataQueue(&Ccb->DataQueue[FILE_PIPE_INBOUND]);
|
|
ExFreePool(CcbNonPaged);
|
|
ExFreePool(Ccb);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
InsertTailList(&Fcb->CcbList, &Ccb->CcbEntry);
|
|
|
|
Fcb->CurrentInstances++;
|
|
Fcb->ServerOpenCount++;
|
|
InitializeListHead(&Ccb->IrpList);
|
|
ExInitializeResourceLite(&Ccb->NonPagedCcb->Lock);
|
|
*NewCcb = Ccb;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* EOF */
|