[NPFS_NEW]

* Beginnings of windows-compatible NPFS driver. Still rough WIP, supports CreateNamedPipe and Create IRPs for now only. This is mainly to lay out all the structures (VCB, DCB, FCB and CCB). Work on read/write (and hence data queue management) is next. Brought to you by Alex Ionescu.

svn path=/trunk/; revision=59996
This commit is contained in:
Amine Khaldi 2013-09-07 15:32:29 +00:00
parent 903ab584cf
commit 73ca298c46
12 changed files with 1920 additions and 0 deletions

View file

@ -7,4 +7,5 @@ add_subdirectory(fs_rec)
add_subdirectory(msfs)
add_subdirectory(mup)
add_subdirectory(npfs)
add_subdirectory(npfs_new)
add_subdirectory(ntfs)

View file

@ -0,0 +1,17 @@
list(APPEND SOURCE
create.c
datasup.c
fileobsup.c
main.c
prefxsup.c
secursup.c
statesup.c
strucsup.c
waitsup.c)
add_library(npfs_new SHARED ${SOURCE})
set_module_type(npfs_new kernelmodedriver)
add_importlibs(npfs_new ntoskrnl hal)
add_pch(npfs_new npfs.h)
add_cd_file(TARGET npfs_new DESTINATION reactos/system32/drivers FOR all)

View file

@ -0,0 +1,726 @@
#include "npfs.h"
VOID
NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,
IN BOOLEAN SecondList,
IN PLIST_ENTRY List)
{
PLIST_ENTRY NextEntry, ListHead;
PIRP Irp;
ULONG i;
PAGED_CODE();
ListHead = &Dcb->NotifyList;
for (i = 0; i < 2; i++)
{
while (!IsListEmpty(ListHead))
{
NextEntry = RemoveHeadList(ListHead);
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
if (IoSetCancelRoutine(Irp, NULL))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, NextEntry);
}
else
{
InitializeListHead(NextEntry);
}
}
if (!SecondList) break;
ListHead = &Dcb->NotifyList2;
}
}
IO_STATUS_BLOCK
NTAPI
NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess)
{
IO_STATUS_BLOCK Status;
PAGED_CODE();
NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
++NpVcb->ReferenceCount;
Status.Information = 1;
Status.Status = STATUS_SUCCESS;
return Status;
}
IO_STATUS_BLOCK
NTAPI
NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PLIST_ENTRY List)
{
IO_STATUS_BLOCK Status;
PNP_ROOT_DCB_FCB Ccb;
PAGED_CODE();
Status.Status = NpCreateRootDcbCcb(&Ccb);
if (NT_SUCCESS(Status.Status))
{
NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
++Dcb->CurrentInstances;
Status.Information = 1;
Status.Status = STATUS_SUCCESS;
}
else
{
Status.Information = 0;
}
return Status;
}
IO_STATUS_BLOCK
NTAPI
NpCreateClientEnd(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PACCESS_STATE AccessState,
IN KPROCESSOR_MODE PreviousMode,
IN PETHREAD Thread,
IN PLIST_ENTRY List)
{
PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
BOOLEAN AccessGranted;
ACCESS_MASK GrantedAccess;
PPRIVILEGE_SET Privileges;
UNICODE_STRING ObjectTypeName;
IO_STATUS_BLOCK IoStatus;
USHORT NamedPipeConfiguration;
PLIST_ENTRY NextEntry, ListHead;
PNP_CCB Ccb = NULL;
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 0;
Privileges = NULL;
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(SubjectSecurityContext);
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
SubjectSecurityContext,
TRUE,
DesiredAccess & ~4,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
PreviousMode,
&GrantedAccess,
&IoStatus.Status);
if (Privileges)
{
SeAppendPrivileges(AccessState, Privileges);
SeFreePrivileges(Privileges);
}
if (AccessGranted)
{
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000);
}
ObjectTypeName.Buffer = L"NamedPipe";
ObjectTypeName.Length = 18;
SeOpenObjectAuditAlarm(&ObjectTypeName,
NULL,
&FileObject->FileName,
Fcb->SecurityDescriptor,
AccessState,
FALSE,
AccessGranted,
PreviousMode,
&AccessState->GenerateOnClose);
SeUnlockSubjectContext(SubjectSecurityContext);
if (!AccessGranted) return IoStatus;
if (((GrantedAccess & 1) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
((GrantedAccess & 2) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
if (!(GrantedAccess & 3)) SecurityQos = NULL;
ListHead = &Fcb->CcbList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
NextEntry = NextEntry->Flink;
}
if (NextEntry == ListHead)
{
IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
return IoStatus;
}
IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
if (!NT_SUCCESS(IoStatus.Status))
{
NpUninitializeSecurity(Ccb);
return IoStatus;
}
Ccb->ClientSession = NULL;
Ccb->Process = IoThreadToProcess(Thread);
IoStatus.Information = 1;
IoStatus.Status = STATUS_SUCCESS;
return IoStatus;
}
NTSTATUS
NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
UNICODE_STRING FileName;
PFILE_OBJECT FileObject;
PFILE_OBJECT RelatedFileObject;
NODE_TYPE_CODE Type;
PNP_CCB Ccb;
PNP_FCB Fcb;
PNP_DCB Dcb;
ACCESS_MASK DesiredAccess;
LIST_ENTRY List;
UNICODE_STRING Prefix;
InitializeListHead(&List);
IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
RelatedFileObject = FileObject->RelatedFileObject;
FileName = FileObject->FileName;
DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
DPRINT1("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
DPRINT1("FileObject %p\n", FileObject);
DPRINT1("FileName %wZ\n", &FileObject->FileName);
DPRINT1("FileName->Length: %hu RelatedFileObject: %p\n", FileName.Length, RelatedFileObject);
FsRtlEnterFileSystem();
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
if (RelatedFileObject)
{
Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
}
else
{
Type = 0;
Fcb = NULL;
Ccb = NULL;
}
if (FileName.Length)
{
if ((FileName.Length == sizeof(WCHAR)) &&
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
!(RelatedFileObject))
{
Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
FileObject,
DesiredAccess,
&List);
}
}
else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
{
Irp->IoStatus = NpOpenNamedPipeFileSystem(FileObject,
DesiredAccess);
}
else if (Type == NPFS_NTC_ROOT_DCB)
{
Irp->IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
FileObject,
DesiredAccess,
&List);
}
else
{
// Status = NpTranslateAlias(&FileName);; // ignore this for now
// if (!NT_SUCCESS(Status)) goto Quickie;
if (RelatedFileObject)
{
if (Type == NPFS_NTC_ROOT_DCB)
{
Dcb = (PNP_DCB)Ccb;
Irp->IoStatus.Status = NpFindRelativePrefix(Dcb,
&FileName,
1,
&Prefix,
&Fcb);
if (!NT_SUCCESS(Irp->IoStatus.Status)) goto Quickie;
}
else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
else
{
Prefix.Length = 0;
}
}
else
{
if ((FileName.Length <= sizeof(WCHAR)) ||
(FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Fcb = NpFindPrefix(&FileName, 1, &Prefix);
}
if (Prefix.Length)
{
Irp->IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
STATUS_OBJECT_NAME_NOT_FOUND :
STATUS_OBJECT_NAME_INVALID;
}
if (!Fcb->CurrentInstances)
{
Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
Irp->IoStatus = NpCreateClientEnd(Fcb,
FileObject,
DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->SecurityQos,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Irp->Tail.Overlay.Thread,
&List);
}
}
Quickie:
ExReleaseResourceLite(&NpVcb->Lock);
ASSERT(IsListEmpty(&List) == TRUE);
FsRtlExitFileSystem();
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
IO_STATUS_BLOCK
NTAPI
NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
IN PFILE_OBJECT FileObject,
IN ACCESS_MASK DesiredAccess,
IN PACCESS_STATE AccessState,
IN KPROCESSOR_MODE PreviousMode,
IN ULONG Disposition,
IN ULONG ShareAccess,
IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
IN PEPROCESS Process,
OUT PLIST_ENTRY List)
{
PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
IO_STATUS_BLOCK IoStatus;
UNICODE_STRING ObjectTypeName;
ACCESS_MASK GrantedAccess;
PNP_CCB Ccb;
PPRIVILEGE_SET Privileges;
USHORT NamedPipeConfiguration, CheckShareAccess;
BOOLEAN AccessGranted;
PAGED_CODE();
Privileges = NULL;
NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
SubjectSecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(SubjectSecurityContext);
AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
SubjectSecurityContext,
TRUE,
DesiredAccess | 4,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
PreviousMode,
&GrantedAccess,
&IoStatus.Status);
if (Privileges)
{
SeAppendPrivileges(AccessState, Privileges);
SeFreePrivileges(Privileges);
}
if (AccessGranted)
{
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000);
}
ObjectTypeName.Buffer = L"NamedPipe";
ObjectTypeName.Length = 18;
SeOpenObjectAuditAlarm(&ObjectTypeName,
NULL,
&FileObject->FileName,
Fcb->SecurityDescriptor,
AccessState,
FALSE,
AccessGranted,
PreviousMode,
&AccessState->GenerateOnClose);
SeUnlockSubjectContext(SubjectSecurityContext);
if ( !AccessGranted ) return IoStatus;
if ( Fcb->CurrentInstances >= Fcb->MaximumInstances )
{
IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
return IoStatus;
}
if ( Disposition == FILE_CREATE )
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
CheckShareAccess = 0;
if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
{
CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
{
CheckShareAccess = FILE_SHARE_READ;
}
else if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
{
CheckShareAccess = FILE_SHARE_WRITE;
}
if ( CheckShareAccess != ShareAccess )
{
IoStatus.Status = STATUS_ACCESS_DENIED;
return IoStatus;
}
IoStatus.Status = NpCreateCcb(Fcb,
FileObject,
FILE_PIPE_LISTENING_STATE,
Parameters->ReadMode & 0xFF,
Parameters->CompletionMode & 0xFF,
Parameters->InboundQuota,
Parameters->OutboundQuota,
&Ccb);
if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue,
&Fcb->FullName,
FALSE,
List);
if (!NT_SUCCESS(IoStatus.Status))
{
--Ccb->Fcb->CurrentInstances;
NpDeleteCcb(Ccb, List);
return IoStatus;
}
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
Ccb->ServerFileObject = FileObject;
NpCheckForNotify(Fcb->ParentDcb, 0, List);
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 1;
return IoStatus;
}
NTSTATUS
NTAPI
NpCreateNewNamedPipe(IN PNP_DCB Dcb,
IN PFILE_OBJECT FileObject,
IN UNICODE_STRING PipeName,
IN ACCESS_MASK DesiredAccess,
IN PACCESS_STATE AccessState,
IN USHORT Disposition,
IN USHORT ShareAccess,
IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
IN PEPROCESS Process,
IN PLIST_ENTRY List,
IN PIO_STATUS_BLOCK IoStatus)
{
NTSTATUS Status;
USHORT NamedPipeConfiguration;
PSECURITY_SUBJECT_CONTEXT SecurityContext;
PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor;
PNP_CCB Ccb;
PNP_FCB Fcb;
PAGED_CODE();
if (!(Parameters->TimeoutSpecified) ||
!(Parameters->MaximumInstances) ||
(Parameters->DefaultTimeout.HighPart >= 0))
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
if (Disposition == FILE_OPEN)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Quickie;
}
if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE))
{
NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
}
else if (ShareAccess == FILE_SHARE_READ)
{
NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
}
else if (ShareAccess == FILE_SHARE_WRITE)
{
NamedPipeConfiguration = FILE_PIPE_INBOUND;
}
else
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
if ( !Parameters->NamedPipeType && Parameters->ReadMode == 1 )
{
Status = STATUS_INVALID_PARAMETER;
goto Quickie;
}
Status = NpCreateFcb(Dcb,
&PipeName,
Parameters->MaximumInstances,
Parameters->DefaultTimeout,
NamedPipeConfiguration,
Parameters->NamedPipeType & 0xFFFF,
&Fcb);
if (!NT_SUCCESS(Status)) goto Quickie;
Status = NpCreateCcb(Fcb,
FileObject,
FILE_PIPE_LISTENING_STATE,
Parameters->ReadMode & 0xFF,
Parameters->CompletionMode & 0xFF,
Parameters->InboundQuota,
Parameters->OutboundQuota,
&Ccb);
if (!NT_SUCCESS(Status))
{
NpDeleteFcb(Fcb, List);
goto Quickie;
}
SecurityContext = &AccessState->SubjectSecurityContext;
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
Status = SeAssignSecurity(0,
AccessState->SecurityDescriptor,
&SecurityDescriptor,
0,
SecurityContext,
IoGetFileObjectGenericMapping(),
PagedPool);
SeUnlockSubjectContext(SecurityContext);
if (!NT_SUCCESS(Status))
{
NpDeleteCcb(Ccb, List);
NpDeleteFcb(Fcb, List);
goto Quickie;
}
Status = ObLogSecurityDescriptor(SecurityDescriptor,
&CachedSecurityDescriptor,
1);
ExFreePool(SecurityDescriptor);
if (!NT_SUCCESS(Status))
{
NpDeleteCcb(Ccb, List);
NpDeleteFcb(Fcb, List);
goto Quickie;
}
Fcb->SecurityDescriptor = CachedSecurityDescriptor;
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
Ccb->ServerFileObject = FileObject;
NpCheckForNotify(Dcb, 1, List);
IoStatus->Status = 0;
IoStatus->Information = 2;
return STATUS_SUCCESS;
Quickie:
IoStatus->Information = 0;
IoStatus->Status = Status;
return Status;
}
NTSTATUS
NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PEXTENDED_IO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PFILE_OBJECT RelatedFileObject;
USHORT Disposition, ShareAccess;
PEPROCESS Process;
LIST_ENTRY LocalList;
UNICODE_STRING FileName;
PNP_FCB Fcb;
UNICODE_STRING Prefix;
PNAMED_PIPE_CREATE_PARAMETERS Parameters;
IO_STATUS_BLOCK IoStatus;
DPRINT1("NpFsdCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
InitializeListHead(&LocalList);
Process = IoGetRequestorProcess(Irp);
IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
RelatedFileObject = FileObject->RelatedFileObject;
Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
Parameters = IoStack->Parameters.CreatePipe.Parameters;
FileName.Buffer = FileObject->FileName.Buffer;
FileName.Length = FileObject->FileName.Length;
FileName.MaximumLength = FileObject->FileName.MaximumLength;
IoStatus.Status = STATUS_SUCCESS;
IoStatus.Information = 0;
FsRtlEnterFileSystem();
ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
DPRINT1("FileObject %p\n", FileObject);
DPRINT1("FileName %wZ\n", &FileObject->FileName);
DPRINT1("FileName->Length: %hu RelatedFileObject: %p\n", FileName.Length, RelatedFileObject);
if ( RelatedFileObject )
{
Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
if (!(Fcb) ||
(Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
(FileName.Length < sizeof(WCHAR)) ||
(FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
&FileName,
TRUE,
&Prefix,
&Fcb);
if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
}
else
{
if ( FileName.Length <= 2u || *FileName.Buffer != '\\' )
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Fcb = NpFindPrefix(&FileName, 1u, &Prefix);
}
if ( Prefix.Length )
{
if (Fcb->NodeType == NPFS_NTC_ROOT_DCB )
{
IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
FileObject,
FileName,
IoStack->Parameters.CreatePipe.
SecurityContext->DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
Disposition,
ShareAccess,
Parameters,
Process,
&LocalList,
&Irp->IoStatus);
goto Quickie;
}
else
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
}
if (Fcb->NodeType != NPFS_NTC_FCB )
{
IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
goto Quickie;
}
Irp->IoStatus = NpCreateExistingNamedPipe(Fcb,
FileObject,
IoStack->Parameters.CreatePipe.
SecurityContext->DesiredAccess,
IoStack->Parameters.CreatePipe.
SecurityContext->AccessState,
IoStack->Flags &
SL_FORCE_ACCESS_CHECK ?
UserMode : Irp->RequestorMode,
Disposition,
ShareAccess,
Parameters,
Process,
&LocalList);
Quickie:
ExReleaseResourceLite(&NpVcb->Lock);
ASSERT(IsListEmpty(&LocalList));
FsRtlExitFileSystem();
Irp->IoStatus = IoStatus;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return IoStatus.Status;
}

View file

@ -0,0 +1,30 @@
#include "npfs.h"
NTSTATUS
NTAPI
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue)
{
PAGED_CODE();
ASSERT(DataQueue->QueueState == Empty);
RtlZeroMemory(DataQueue, sizeof(*DataQueue));
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN ULONG Quota)
{
PAGED_CODE();
DataQueue->BytesInQueue = 0;
DataQueue->EntriesInQueue = 0;
DataQueue->QuotaUsed = 0;
DataQueue->ByteOffset = 0;
DataQueue->QueueState = Empty;
DataQueue->Quota = Quota;
InitializeListHead(&DataQueue->List);
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,72 @@
#include "npfs.h"
NODE_TYPE_CODE
NTAPI
NpDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVOID* PrimaryContext OPTIONAL,
OUT PNP_CCB* Ccb,
OUT PBOOLEAN ServerSide OPTIONAL)
{
ULONG_PTR Context;
PNP_CCB Node;
PAGED_CODE();
Context = (ULONG_PTR)FileObject->FsContext;
if ((Context) && (Context != 1))
{
if (ServerSide) *ServerSide = Context & 1;
Node = (PVOID)(Context & ~1);
switch (Node->NodeType)
{
case NPFS_NTC_VCB:
return NPFS_NTC_VCB;
case NPFS_NTC_ROOT_DCB:
*Ccb = FileObject->FsContext2;
if (PrimaryContext) *PrimaryContext = Node;
return NPFS_NTC_ROOT_DCB;
case NPFS_NTC_CCB:
*Ccb = Node;
if (PrimaryContext) *PrimaryContext = Node->Fcb;
return NPFS_NTC_CCB;
default:
KeBugCheckEx(NPFS_FILE_SYSTEM, 0xB0108, Node->NodeType, 0, 0);
break;
}
}
return 0;
}
VOID
NTAPI
NpSetFileObject(IN PFILE_OBJECT FileObject,
IN PVOID PrimaryContext,
IN PVOID Ccb,
IN BOOLEAN ServerSide)
{
BOOLEAN FileIsPipe;
PAGED_CODE();
if (!FileObject) return;
if ((PrimaryContext) && (((PNP_CCB)PrimaryContext)->NodeType == NPFS_NTC_CCB))
{
FileIsPipe = TRUE;
if (ServerSide) PrimaryContext = (PVOID)((ULONG_PTR)PrimaryContext | 1);
}
else
{
FileIsPipe = FALSE;
}
FileObject->FsContext = PrimaryContext;
FileObject->FsContext2 = Ccb;
FileObject->PrivateCacheMap = (PVOID)1;
if (FileIsPipe) FileObject->Flags |= FO_NAMED_PIPE;
}

View file

@ -0,0 +1,201 @@
#include "npfs.h"
PDEVICE_OBJECT NpfsDeviceObject;
NTSTATUS
NTAPI
NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
UNIMPLEMENTED;
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName;
NTSTATUS Status;
UNREFERENCED_PARAMETER(RegistryPath);
DPRINT1("Next-Generation NPFS-Lite\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = NpFsdCreate;
DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NpFsdClose;
DriverObject->MajorFunction[IRP_MJ_READ] = NpFsdRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = NpFsdWrite;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = NpFsdQueryInformation;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = NpFsdSetInformation;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = NpFsdQueryVolumeInformation;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpFsdCleanup;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpFsdFlushBuffers;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = NpFsdDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = NpFsdFileSystemControl;
// DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =
// NpfsQuerySecurity;
// DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =
// NpfsSetSecurity;
DriverObject->DriverUnload = NULL;
RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
Status = IoCreateDevice(DriverObject,
sizeof(NP_VCB),
&DeviceName,
FILE_DEVICE_NAMED_PIPE,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create named pipe device! (Status %lx)\n", Status);
return Status;
}
/* Initialize the device object */
NpfsDeviceObject = DeviceObject;
DeviceObject->Flags |= DO_DIRECT_IO;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* Initialize the Volume Control Block (VCB) */
NpVcb = DeviceObject->DeviceExtension;
NpInitializeVcb();
Status = NpCreateRootDcb();
ASSERT(Status == STATUS_SUCCESS);
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,318 @@
//
// System Headers
//
#include <ntifs.h>
#include <ntndk.h>
#define UNIMPLEMENTED
#define DPRINT1 DbgPrint
//
// Allow Microsoft Extensions
//
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable:4214)
#pragma warning(disable:4100)
#endif
//
// Node Type Codes for NPFS
//
#define NPFS_NTC_VCB 1
#define NPFS_NTC_ROOT_DCB 2
#define NPFS_NTC_FCB 4
#define NPFS_NTC_CCB 6
#define NPFS_NTC_NONPAGED_CCB 7
#define NPFS_NTC_ROOT_DCB_CCB 8
typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
//
// Data Queue States
//
typedef enum _NP_DATA_QUEUE_STATE
{
Empty = 2
} NP_DATA_QUEUE_STATE;
//
// An Input or Output Data Queue. Each CCB has two of these.
//
typedef struct _NP_DATA_QUEUE
{
LIST_ENTRY List;
ULONG QueueState;
ULONG BytesInQueue;
ULONG EntriesInQueue;
ULONG QuotaUsed;
ULONG ByteOffset;
ULONG Quota;
} NP_DATA_QUEUE, *PNP_DATA_QUEUE;
//
// A Wait Queue. Only the VCB has one of these.
//
typedef struct _NP_WAIT_QUEUE
{
LIST_ENTRY WaitList;
KSPIN_LOCK WaitLock;
} NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
//
// The CCB for the Root DCB
//
typedef struct _NP_ROOT_DCB_CCB
{
NODE_TYPE_CODE NodeType;
PVOID Unknown;
ULONG Unknown2;
} NP_ROOT_DCB_CCB, *PNP_ROOT_DCB_FCB;
//
// The header that both FCB and DCB share
//
typedef struct _NP_CB_HEADER
{
NODE_TYPE_CODE NodeType;
LIST_ENTRY DcbEntry;
PVOID ParentDcb;
ULONG CurrentInstances;
ULONG OtherCount;
PSECURITY_DESCRIPTOR SecurityDescriptor;
} NP_CB_HEADER, *PNP_CB_HEADER;
//
// The footer that both FCB and DCB share
//
typedef struct _NP_CB_FOOTER
{
UNICODE_STRING FullName;
UNICODE_STRING ShortName;
UNICODE_PREFIX_TABLE_ENTRY PrefixTableEntry;
} NP_CB_FOOTER;
//
// A Directory Control Block (DCB)
//
typedef struct _NP_DCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// DCB-specific data
//
LIST_ENTRY NotifyList;
LIST_ENTRY NotifyList2;
LIST_ENTRY FcbList;
//
// Common Footer
//
NP_CB_FOOTER;
} NP_DCB, *PNP_DCB;
//
// A File Control BLock (FCB)
//
typedef struct _NP_FCB
{
//
// Common Header
//
NP_CB_HEADER;
//
// FCB-specific fields
//
ULONG MaximumInstances;
USHORT NamedPipeConfiguration;
USHORT NamedPipeType;
LARGE_INTEGER Timeout;
LIST_ENTRY CcbList;
//
// Common Footer
//
NP_CB_FOOTER;
} NP_FCB, *PNP_FCB;
//
// The nonpaged portion of the CCB
//
typedef struct _NP_NONPAGED_CCB
{
NODE_TYPE_CODE NodeType;
PVOID EventBufferClient;
PVOID EventBufferServer;
ERESOURCE Lock;
} NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
//
// A Client Control Block (CCB)
//
typedef struct _NP_CCB
{
NODE_TYPE_CODE NodeType;
UCHAR NamedPipeState;
UCHAR ClientReadMode:1;
UCHAR ClientCompletionMode:1;
UCHAR ServerReadMode:1;
UCHAR ClientReservedFlags:6;
UCHAR ServerCompletionMode:1;
UCHAR ServerReservedFlags:6;
SECURITY_QUALITY_OF_SERVICE ClientQos;
LIST_ENTRY CcbEntry;
PNP_FCB Fcb;
PFILE_OBJECT ClientFileObject;
PFILE_OBJECT ServerFileObject;
PEPROCESS Process;
PVOID ClientSession;
PNP_NONPAGED_CCB NonPagedCcb;
NP_DATA_QUEUE InQueue;
NP_DATA_QUEUE OutQueue;
PSECURITY_CLIENT_CONTEXT ClientContext;
LIST_ENTRY IrpList;
} NP_CCB, *PNP_CCB;
//
// A Volume Control Block (VCB)
//
typedef struct _NP_VCB
{
NODE_TYPE_CODE NodeType;
ULONG ReferenceCount;
PNP_DCB RootDcb;
UNICODE_PREFIX_TABLE PrefixTable;
ERESOURCE Lock;
RTL_GENERIC_TABLE EventTable;
NP_WAIT_QUEUE WaitQueue;
} NP_VCB, *PNP_VCB;
extern PNP_VCB NpVcb;
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
NTSTATUS
NTAPI
NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
NTSTATUS
NTAPI
NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
IN ULONG Quota);
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);
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);
NTSTATUS
NTAPI
NpCreateRootDcb(VOID);
NTSTATUS
NTAPI
NpCreateRootDcbCcb(IN PNP_ROOT_DCB_FCB* NewRootCcb);
VOID
NTAPI
NpInitializeVcb(VOID);
VOID
NTAPI
NpDeleteCcb(IN PNP_CCB Ccb,
IN PLIST_ENTRY ListEntry);
VOID
NTAPI
NpDeleteFcb(IN PNP_FCB Fcb,
IN PLIST_ENTRY ListEntry);
NTSTATUS
NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List);
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb);
NTSTATUS
NTAPI
NpInitializeSecurity(IN PNP_CCB Ccb,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PETHREAD Thread);
VOID
NTAPI
NpSetFileObject(IN PFILE_OBJECT FileObject,
IN PVOID PrimaryContext,
IN PVOID Ccb,
IN BOOLEAN ServerSide);
NODE_TYPE_CODE
NTAPI
NpDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVOID* PrimaryContext OPTIONAL,
OUT PNP_CCB* Ccb,
OUT PBOOLEAN ServerSide OPTIONAL);
PNP_FCB
NTAPI
NpFindPrefix(IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix);
NTSTATUS
NTAPI
NpFindRelativePrefix(IN PNP_DCB Dcb,
IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix,
OUT PNP_FCB *FoundFcb);
VOID
NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,
IN BOOLEAN SecondList,
IN PLIST_ENTRY List);
NTSTATUS
NTAPI
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN PUNICODE_STRING PipeName,
IN NTSTATUS Status,
IN PLIST_ENTRY ListEntry);

View file

@ -0,0 +1,77 @@
#include "npfs.h"
PNP_FCB
NTAPI
NpFindPrefix(IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix)
{
PUNICODE_PREFIX_TABLE_ENTRY Entry;
PNP_FCB Fcb;
PAGED_CODE();
Entry = RtlFindUnicodePrefix(&NpVcb->PrefixTable,
Name,
CaseInsensitiveIndex);
if (!Entry) KeBugCheckEx(NPFS_FILE_SYSTEM, 0x100065u, 0, 0, 0);
Fcb = CONTAINING_RECORD(Entry, NP_FCB, PrefixTableEntry);
Prefix->Length = Name->Length - Fcb->FullName.Length;
Prefix->MaximumLength = Prefix->Length;
Prefix->Buffer = &Name->Buffer[Fcb->FullName.Length / sizeof(WCHAR)];
if ((Prefix->Length) && (Prefix->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
{
Prefix->Length -= sizeof(WCHAR);
Prefix->MaximumLength -= sizeof(WCHAR);
++Prefix->Buffer;
}
return Fcb;
}
NTSTATUS
NTAPI
NpFindRelativePrefix(IN PNP_DCB Dcb,
IN PUNICODE_STRING Name,
IN ULONG CaseInsensitiveIndex,
IN PUNICODE_STRING Prefix,
OUT PNP_FCB *FoundFcb)
{
PWCHAR Buffer;
PNP_FCB Fcb;
UNICODE_STRING RootName;
USHORT Length, MaximumLength;
PAGED_CODE();
Length = Name->Length;
MaximumLength = Length + sizeof(OBJ_NAME_PATH_SEPARATOR) + sizeof(UNICODE_NULL);
if (MaximumLength < Length) return STATUS_INVALID_PARAMETER;
ASSERT(Dcb->NodeType == NPFS_NTC_ROOT_DCB);
Buffer = ExAllocatePoolWithTag(PagedPool, MaximumLength, 'nFpN');
if (!Buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
*Buffer = OBJ_NAME_PATH_SEPARATOR;
RtlCopyMemory(Buffer + 1, Name->Buffer, Length);
Buffer[(Length / sizeof(WCHAR)) + 1] = UNICODE_NULL;
RootName.Length = Length + sizeof(OBJ_NAME_PATH_SEPARATOR);
RootName.MaximumLength = MaximumLength;
RootName.Buffer = Buffer;
Fcb = NpFindPrefix(&RootName, CaseInsensitiveIndex, Prefix);
ExFreePool(Buffer);
Prefix->Buffer = &Name->Buffer[(Length - Prefix->Length) / sizeof(WCHAR)];
*FoundFcb = Fcb;
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,65 @@
#include "npfs.h"
VOID
NTAPI
NpUninitializeSecurity(IN PNP_CCB Ccb)
{
PACCESS_TOKEN ClientToken;
PSECURITY_CLIENT_CONTEXT ClientContext;
TOKEN_TYPE TokenType;
PAGED_CODE();
ClientContext = Ccb->ClientContext;
if (!ClientContext) return;
TokenType = SeTokenType(ClientContext->ClientToken);
ClientToken = Ccb->ClientContext->ClientToken;
if ((TokenType == TokenPrimary) || (ClientToken))
{
ObfDereferenceObject(ClientToken);
}
ExFreePool(Ccb->ClientContext);
Ccb->ClientContext = 0;
}
NTSTATUS
NTAPI
NpInitializeSecurity(IN PNP_CCB Ccb,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN PETHREAD Thread)
{
PSECURITY_CLIENT_CONTEXT ClientContext;
NTSTATUS Status;
PAGED_CODE();
if (SecurityQos)
{
Ccb->ClientQos = *SecurityQos;
}
else
{
Ccb->ClientQos.Length = 12;
Ccb->ClientQos.ImpersonationLevel = 2;
Ccb->ClientQos.ContextTrackingMode = 1;
Ccb->ClientQos.EffectiveOnly = 1;
}
NpUninitializeSecurity(Ccb);
if (Ccb->ClientQos.ContextTrackingMode)
{
Status = 0;
Ccb->ClientContext = 0;
return Status;
}
ClientContext = ExAllocatePoolWithTag(PagedPool, sizeof(*ClientContext), 'sFpN');
Ccb->ClientContext = ClientContext;
if (!ClientContext) return STATUS_INSUFFICIENT_RESOURCES;
Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, ClientContext);
if (Status >= 0) return Status;
ExFreePool(Ccb->ClientContext);
Ccb->ClientContext = 0;
return Status;
}

View file

@ -0,0 +1,39 @@
#include "npfs.h"
NTSTATUS
NTAPI
NpSetConnectedPipeState(IN PNP_CCB Ccb,
IN PFILE_OBJECT FileObject,
IN PLIST_ENTRY List)
{
PLIST_ENTRY NextEntry;
PIRP Irp;
ASSERT(Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE);
Ccb->ClientReadMode = FILE_PIPE_BYTE_STREAM_MODE;
Ccb->ClientCompletionMode = FILE_PIPE_QUEUE_OPERATION;
Ccb->NamedPipeState = FILE_PIPE_CONNECTED_STATE;
Ccb->ClientFileObject = FileObject;
NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, FALSE);
while (!IsListEmpty(&Ccb->IrpList))
{
NextEntry = RemoveHeadList(&Ccb->IrpList);
Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
if (IoSetCancelRoutine(Irp, NULL))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
InsertTailList(List, NextEntry);
}
else
{
InitializeListHead(NextEntry);
}
}
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,339 @@
#include "npfs.h"
#define UNIMPLEMENTED
PWCHAR NpRootDCBName = L"\\";
PNP_VCB NpVcb;
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)
{
UNIMPLEMENTED;
return FALSE;
}
VOID
NTAPI
NpDeleteFcb(IN PNP_FCB Fcb,
IN PLIST_ENTRY ListEntry)
{
PNP_DCB Dcb;
PAGED_CODE();
Dcb = Fcb->ParentDcb;
if (!Fcb->CurrentInstances) KeBugCheckEx(NPFS_FILE_SYSTEM, 0x17025F, 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->EventBufferClient);
NpDeleteEventTableEntry(&NpVcb->EventTable,
Ccb->NonPagedCcb->EventBufferServer);
NpUninitializeDataQueue(&Ccb->InQueue);
NpUninitializeDataQueue(&Ccb->OutQueue);
NpCheckForNotify(Ccb->Fcb->ParentDcb, 0, ListEntry);
ExDeleteResourceLite(&Ccb->NonPagedCcb->Lock);
NpUninitializeSecurity(Ccb);
if ( Ccb->ClientSession )
{
ExFreePool(Ccb->ClientSession);
Ccb->ClientSession = 0;
}
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), 'CFpN');
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)
{
KeBugCheckEx(0x25, 0x1700F3, 0, 0, 0);
}
NpVcb->RootDcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Dcb), 'DFpN');
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 = 2;
Dcb->FullName.MaximumLength = 4;
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))
{
KeBugCheckEx(0x25u, 0x170128, 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;
ULONG BufferOffset;
USHORT PipeNameLength;
PAGED_CODE();
PipeNameLength = PipeName->Length;
if ((PipeNameLength < sizeof(WCHAR)) ||
((PipeNameLength + sizeof(WCHAR)) < PipeNameLength) ||
(PipeName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
{
return STATUS_INVALID_PARAMETER;
}
RootPipe = FALSE;
if (PipeNameLength == sizeof(WCHAR))
{
RootPipe = TRUE;
PipeNameLength += sizeof(WCHAR);
}
Fcb = ExAllocatePoolWithTag(PagedPool, sizeof(*Fcb), 'FfpN');
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,
PipeName->Length + (RootPipe ? 4 : 2),
'nFpN');
if (!NameBuffer)
{
ExFreePool(Fcb);
return STATUS_INSUFFICIENT_RESOURCES;
}
InsertTailList(&Dcb->FcbList, &Fcb->DcbEntry);
BufferOffset = 0;
if (RootPipe)
{
*NameBuffer = OBJ_NAME_PATH_SEPARATOR;
BufferOffset = 1;
}
RtlCopyMemory(NameBuffer + BufferOffset, PipeName->Buffer, PipeNameLength);
NameBuffer[BufferOffset + (PipeNameLength / sizeof(WCHAR))] = UNICODE_NULL;
Fcb->FullName.Length = PipeNameLength - sizeof(WCHAR);
Fcb->FullName.MaximumLength = PipeNameLength;
Fcb->FullName.Buffer = NameBuffer;
Fcb->ShortName.MaximumLength = PipeNameLength - sizeof(WCHAR);
Fcb->ShortName.Length = PipeNameLength - 2 * sizeof(WCHAR);
Fcb->ShortName.Buffer = NameBuffer + 1;
if (!RtlInsertUnicodePrefix(&NpVcb->PrefixTable,
&Fcb->FullName,
&Fcb->PrefixTableEntry))
{
KeBugCheckEx(NPFS_FILE_SYSTEM, 0x170222, 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), 'cFpN');
if (!Ccb) return STATUS_INSUFFICIENT_RESOURCES;
CcbNonPaged = ExAllocatePoolWithTag(NonPagedPool, sizeof(*CcbNonPaged), 'cFpN');
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->ServerFileObject = FileObject;
Ccb->Fcb = Fcb;
Ccb->NamedPipeState = State;
Ccb->ServerReadMode = ReadMode;
Ccb->ServerCompletionMode = CompletionMode;
Status = NpInitializeDataQueue(&Ccb->InQueue, InQuota);
if (!NT_SUCCESS(Status))
{
ExFreePool(CcbNonPaged);
ExFreePool(Ccb);
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = NpInitializeDataQueue(&Ccb->OutQueue, InQuota);
if (!NT_SUCCESS(Status))
{
NpUninitializeDataQueue(&Ccb->InQueue);
ExFreePool(CcbNonPaged);
ExFreePool(Ccb);
return STATUS_INSUFFICIENT_RESOURCES;
}
InsertTailList(&Fcb->CcbList, &Ccb->CcbEntry);
InitializeListHead(&Ccb->IrpList);
ExInitializeResourceLite(&Ccb->NonPagedCcb->Lock);
*NewCcb = Ccb;
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,35 @@
#include "npfs.h"
VOID
NTAPI
NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue)
{
InitializeListHead(&WaitQueue->WaitList);
KeInitializeSpinLock(&WaitQueue->WaitLock);
}
NTSTATUS
NTAPI
NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
IN PUNICODE_STRING PipeName,
IN NTSTATUS Status,
IN PLIST_ENTRY ListEntry)
{
UNICODE_STRING DestinationString;
KIRQL OldIrql;
PWCHAR Buffer;
Buffer = ExAllocatePoolWithTag(NonPagedPool, PipeName->Length,'tFpN');
if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlInitEmptyUnicodeString(&DestinationString, Buffer, PipeName->Length);
RtlUpcaseUnicodeString(&DestinationString, PipeName, FALSE);
OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
ASSERT(IsListEmpty(&WaitQueue->WaitList) == TRUE);
KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
ExFreePool(DestinationString.Buffer);
return STATUS_SUCCESS;
}