xref: /reactos/drivers/filesystems/npfs/create.c (revision 257923ca)
1 /*
2  * PROJECT:     ReactOS Named Pipe FileSystem
3  * LICENSE:     BSD - See COPYING.ARM in the top level directory
4  * FILE:        drivers/filesystems/npfs/create.c
5  * PURPOSE:     Pipes Creation
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "npfs.h"
12 
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID   (NPFS_BUGCHECK_CREATE)
15 
16 /* FUNCTIONS ******************************************************************/
17 
18 VOID
19 NTAPI
NpCheckForNotify(IN PNP_DCB Dcb,IN BOOLEAN SecondList,IN PLIST_ENTRY List)20 NpCheckForNotify(IN PNP_DCB Dcb,
21                  IN BOOLEAN SecondList,
22                  IN PLIST_ENTRY List)
23 {
24     PLIST_ENTRY NextEntry, ListHead;
25     PIRP Irp;
26     ULONG i;
27     PAGED_CODE();
28 
29     ListHead = &Dcb->NotifyList;
30     for (i = 0; i < 2; i++)
31     {
32         ASSERT(IsListEmpty(ListHead));
33         while (!IsListEmpty(ListHead))
34         {
35             NextEntry = RemoveHeadList(ListHead);
36 
37             Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
38 
39             if (IoSetCancelRoutine(Irp, NULL))
40             {
41                 Irp->IoStatus.Status = STATUS_SUCCESS;
42                 InsertTailList(List, NextEntry);
43             }
44             else
45             {
46                 InitializeListHead(NextEntry);
47             }
48         }
49 
50         if (!SecondList) break;
51         ListHead = &Dcb->NotifyList2;
52     }
53 }
54 
55 IO_STATUS_BLOCK
56 NTAPI
NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,IN ACCESS_MASK DesiredAccess)57 NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
58                           IN ACCESS_MASK DesiredAccess)
59 {
60     IO_STATUS_BLOCK Status;
61     PAGED_CODE();
62     TRACE("Entered\n");
63 
64     NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
65     ++NpVcb->ReferenceCount;
66 
67     Status.Information = FILE_OPENED;
68     Status.Status = STATUS_SUCCESS;
69     TRACE("Leaving, Status.Status = %lx\n", Status.Status);
70     return Status;
71 }
72 
73 IO_STATUS_BLOCK
74 NTAPI
NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,IN PFILE_OBJECT FileObject,IN ACCESS_MASK DesiredAccess,IN PLIST_ENTRY List)75 NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
76                              IN PFILE_OBJECT FileObject,
77                              IN ACCESS_MASK DesiredAccess,
78                              IN PLIST_ENTRY List)
79 {
80     IO_STATUS_BLOCK IoStatus;
81     PNP_ROOT_DCB_FCB Ccb;
82     PAGED_CODE();
83     TRACE("Entered\n");
84 
85     IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
86     if (NT_SUCCESS(IoStatus.Status))
87     {
88         NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
89         ++Dcb->CurrentInstances;
90 
91         IoStatus.Information = FILE_OPENED;
92         IoStatus.Status = STATUS_SUCCESS;
93     }
94     else
95     {
96         IoStatus.Information = 0;
97     }
98 
99     TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
100     return IoStatus;
101 }
102 
103 IO_STATUS_BLOCK
104 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)105 NpCreateClientEnd(IN PNP_FCB Fcb,
106                   IN PFILE_OBJECT FileObject,
107                   IN ACCESS_MASK DesiredAccess,
108                   IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
109                   IN PACCESS_STATE AccessState,
110                   IN KPROCESSOR_MODE PreviousMode,
111                   IN PETHREAD Thread,
112                   IN PLIST_ENTRY List)
113 {
114     PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
115     BOOLEAN AccessGranted;
116     ACCESS_MASK GrantedAccess;
117     PPRIVILEGE_SET Privileges;
118     UNICODE_STRING ObjectTypeName;
119     IO_STATUS_BLOCK IoStatus;
120     USHORT NamedPipeConfiguration;
121     PLIST_ENTRY NextEntry, ListHead;
122     PNP_CCB Ccb = NULL;
123     TRACE("Entered\n");
124 
125     IoStatus.Information = 0;
126     Privileges = NULL;
127 
128     NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
129 
130     SubjectSecurityContext = &AccessState->SubjectSecurityContext;
131     SeLockSubjectContext(SubjectSecurityContext);
132 
133     AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
134                                   SubjectSecurityContext,
135                                   TRUE,
136                                   DesiredAccess & ~4,
137                                   0,
138                                   &Privileges,
139                                   IoGetFileObjectGenericMapping(),
140                                   PreviousMode,
141                                   &GrantedAccess,
142                                   &IoStatus.Status);
143 
144     if (Privileges)
145     {
146         SeAppendPrivileges(AccessState, Privileges);
147         SeFreePrivileges(Privileges);
148     }
149 
150     if (AccessGranted)
151     {
152         AccessState->PreviouslyGrantedAccess |= GrantedAccess;
153         AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
154     }
155 
156     ObjectTypeName.Buffer = L"NamedPipe";
157     ObjectTypeName.Length = 18;
158     SeOpenObjectAuditAlarm(&ObjectTypeName,
159                            NULL,
160                            &FileObject->FileName,
161                            Fcb->SecurityDescriptor,
162                            AccessState,
163                            FALSE,
164                            AccessGranted,
165                            PreviousMode,
166                            &AccessState->GenerateOnClose);
167     SeUnlockSubjectContext(SubjectSecurityContext);
168     if (!AccessGranted) return IoStatus;
169 
170     if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
171         ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
172     {
173         IoStatus.Status = STATUS_ACCESS_DENIED;
174         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
175         return IoStatus;
176     }
177 
178     if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL;
179 
180     ListHead = &Fcb->CcbList;
181     NextEntry = ListHead->Flink;
182     while (NextEntry != ListHead)
183     {
184         Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
185         if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
186 
187         NextEntry = NextEntry->Flink;
188     }
189 
190     if (NextEntry == ListHead)
191     {
192         IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
193         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
194         return IoStatus;
195     }
196 
197     IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
198     if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
199 
200     IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
201     if (!NT_SUCCESS(IoStatus.Status))
202     {
203         NpUninitializeSecurity(Ccb);
204         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
205         return IoStatus;
206     }
207 
208     Ccb->ClientSession = NULL;
209     Ccb->Process = IoThreadToProcess(Thread);
210 
211     IoStatus.Information = FILE_OPENED;
212     IoStatus.Status = STATUS_SUCCESS;
213     TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
214     return IoStatus;
215 }
216 
217 NTSTATUS
218 NTAPI
NpTranslateAlias(PUNICODE_STRING PipeName)219 NpTranslateAlias(
220     PUNICODE_STRING PipeName)
221 {
222     WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
223     UNICODE_STRING UpcaseString;
224     ULONG Length;
225     PNPFS_ALIAS CurrentAlias;
226     NTSTATUS Status;
227     BOOLEAN BufferAllocated, BackSlash;
228     LONG Result;
229     PAGED_CODE();
230 
231     /* Get the pipe name length and check for empty string */
232     Length = PipeName->Length;
233     if (Length == 0)
234     {
235         return STATUS_SUCCESS;
236     }
237 
238     /* Check if the name starts with a path separator */
239     BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
240     if (BackSlash)
241     {
242         /* We are only interested in the part after the backslash */
243         Length -= sizeof(WCHAR);
244     }
245 
246     /* Check if the length is within our indexed list bounds */
247     if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
248         (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
249     {
250         /* Length is within bounds, use the list by length */
251         CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
252     }
253     else
254     {
255         /* We use the generic list, search for an entry of the right size */
256         CurrentAlias = NpAliasList;
257         while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length))
258         {
259             /* Check if we went past the desired length */
260             if (CurrentAlias->Name.Length > Length)
261             {
262                 /* In this case there is no matching alias, return success */
263                 return STATUS_SUCCESS;
264             }
265 
266             /* Go to the next alias in the list */
267             CurrentAlias = CurrentAlias->Next;
268         }
269     }
270 
271     /* Did we find any alias? */
272     if (CurrentAlias == NULL)
273     {
274         /* Nothing found, no matching alias */
275         return STATUS_SUCCESS;
276     }
277 
278     /* Check whether we can use our stack buffer */
279     if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))
280     {
281         /* Initialize the upcased string */
282         UpcaseString.Buffer = UpcaseBuffer;
283         UpcaseString.MaximumLength = sizeof(UpcaseBuffer);
284 
285         /* Upcase the pipe name */
286         Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
287         NT_ASSERT(NT_SUCCESS(Status));
288         BufferAllocated = FALSE;
289     }
290     else
291     {
292         /* Upcase the pipe name, allocate the string buffer */
293         Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
294         if (!NT_SUCCESS(Status))
295         {
296             return Status;
297         }
298 
299         BufferAllocated = TRUE;
300     }
301 
302     /* Did the original name start with a backslash? */
303     if (BackSlash)
304     {
305         /* Skip it for the comparison */
306         UpcaseString.Buffer++;
307         UpcaseString.Length -= sizeof(WCHAR);
308     }
309 
310     /* Make sure the length matches the "raw" length */
311     NT_ASSERT(UpcaseString.Length == Length);
312     NT_ASSERT(CurrentAlias->Name.Length == Length);
313 
314     /* Loop while we have aliases */
315     do
316     {
317         /* Compare the names and check if they match */
318         Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
319         if (Result == 0)
320         {
321             /* The names match, use the target name */
322             *PipeName = *CurrentAlias->TargetName;
323 
324             /* Did the original name start with a backslash? */
325             if (!BackSlash)
326             {
327                 /* It didn't, so skip it in the target name as well */
328                 PipeName->Buffer++;
329                 PipeName->Length -= sizeof(WCHAR);
330             }
331             break;
332         }
333 
334         /* Check if we went past all string candidates */
335         if (Result < 0)
336         {
337             /* Nothing found, we're done */
338             break;
339         }
340 
341         /* Go to the next alias */
342         CurrentAlias = CurrentAlias->Next;
343 
344         /* Keep looping while we have aliases of the right length */
345     } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
346 
347     /* Did we allocate a buffer? */
348     if (BufferAllocated)
349     {
350         /* Free the allocated buffer */
351         ASSERT(UpcaseString.Buffer != UpcaseBuffer);
352         RtlFreeUnicodeString(&UpcaseString);
353     }
354 
355     return STATUS_SUCCESS;
356 }
357 
358 NTSTATUS
359 NTAPI
NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)360 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
361             IN PIRP Irp)
362 {
363     IO_STATUS_BLOCK IoStatus;
364     PIO_STACK_LOCATION IoStack;
365     UNICODE_STRING FileName;
366     PFILE_OBJECT FileObject;
367     PFILE_OBJECT RelatedFileObject;
368     NODE_TYPE_CODE Type;
369     PNP_CCB Ccb;
370     PNP_FCB Fcb;
371     PNP_DCB Dcb;
372     ACCESS_MASK DesiredAccess;
373     LIST_ENTRY DeferredList;
374     UNICODE_STRING Prefix;
375     TRACE("Entered\n");
376 
377     InitializeListHead(&DeferredList);
378     IoStack = IoGetCurrentIrpStackLocation(Irp);
379     FileObject = IoStack->FileObject;
380     RelatedFileObject = FileObject->RelatedFileObject;
381     FileName = FileObject->FileName;
382     DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
383 
384     IoStatus.Information = 0;
385 
386     FsRtlEnterFileSystem();
387     NpAcquireExclusiveVcb();
388 
389     if (RelatedFileObject)
390     {
391         Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
392     }
393     else
394     {
395         Type = 0;
396         Fcb = NULL;
397         Ccb = NULL;
398     }
399 
400     if (FileName.Length)
401     {
402         if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
403             (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
404             !(RelatedFileObject))
405         {
406             IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
407                                                     FileObject,
408                                                     DesiredAccess,
409                                                     &DeferredList);
410             goto Quickie;
411         }
412     }
413     else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
414     {
415         IoStatus = NpOpenNamedPipeFileSystem(FileObject,
416                                              DesiredAccess);
417         goto Quickie;
418     }
419     else if (Type == NPFS_NTC_ROOT_DCB)
420     {
421         IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
422                                                 FileObject,
423                                                 DesiredAccess,
424                                                 &DeferredList);
425         goto Quickie;
426     }
427 
428     IoStatus.Status = NpTranslateAlias(&FileName);
429     if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
430 
431     if (RelatedFileObject)
432     {
433         if (Type == NPFS_NTC_ROOT_DCB)
434         {
435             Dcb = (PNP_DCB)Ccb;
436             IoStatus.Status = NpFindRelativePrefix(Dcb,
437                                                    &FileName,
438                                                    1,
439                                                    &Prefix,
440                                                    &Fcb);
441             if (!NT_SUCCESS(IoStatus.Status))
442             {
443                 goto Quickie;
444             }
445         }
446         else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
447         {
448             IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
449             goto Quickie;
450         }
451         else
452         {
453             Prefix.Length = 0;
454         }
455     }
456     else
457     {
458         if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
459             (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
460         {
461             IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
462             goto Quickie;
463         }
464 
465         Fcb = NpFindPrefix(&FileName, 1, &Prefix);
466     }
467 
468     if (Prefix.Length)
469     {
470         IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
471                            STATUS_OBJECT_NAME_NOT_FOUND :
472                            STATUS_OBJECT_NAME_INVALID;
473         goto Quickie;
474     }
475 
476     if (Fcb->NodeType != NPFS_NTC_FCB)
477     {
478         IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
479         goto Quickie;
480     }
481 
482     if (!Fcb->ServerOpenCount)
483     {
484         IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
485         goto Quickie;
486     }
487 
488     IoStatus = NpCreateClientEnd(Fcb,
489                                  FileObject,
490                                  DesiredAccess,
491                                  IoStack->Parameters.CreatePipe.
492                                  SecurityContext->SecurityQos,
493                                  IoStack->Parameters.CreatePipe.
494                                  SecurityContext->AccessState,
495                                  IoStack->Flags &
496                                  SL_FORCE_ACCESS_CHECK ?
497                                  UserMode : Irp->RequestorMode,
498                                  Irp->Tail.Overlay.Thread,
499                                  &DeferredList);
500 
501 Quickie:
502     NpReleaseVcb();
503     NpCompleteDeferredIrps(&DeferredList);
504     FsRtlExitFileSystem();
505 
506     Irp->IoStatus = IoStatus;
507     IoCompleteRequest(Irp, IO_NO_INCREMENT);
508     TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
509     return IoStatus.Status;
510 }
511 
512 IO_STATUS_BLOCK
513 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)514 NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
515                           IN PFILE_OBJECT FileObject,
516                           IN ACCESS_MASK DesiredAccess,
517                           IN PACCESS_STATE AccessState,
518                           IN KPROCESSOR_MODE PreviousMode,
519                           IN ULONG Disposition,
520                           IN ULONG ShareAccess,
521                           IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
522                           IN PEPROCESS Process,
523                           OUT PLIST_ENTRY List)
524 {
525     PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
526     IO_STATUS_BLOCK IoStatus;
527     UNICODE_STRING ObjectTypeName;
528     ACCESS_MASK GrantedAccess;
529     PNP_CCB Ccb;
530     PPRIVILEGE_SET Privileges;
531     USHORT NamedPipeConfiguration, CheckShareAccess;
532     BOOLEAN AccessGranted;
533     PAGED_CODE();
534     TRACE("Entered\n");
535 
536     Privileges = NULL;
537 
538     NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
539 
540     SubjectSecurityContext = &AccessState->SubjectSecurityContext;
541     SeLockSubjectContext(SubjectSecurityContext);
542 
543     IoStatus.Information = 0;
544 
545     AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
546                                   SubjectSecurityContext,
547                                   TRUE,
548                                   DesiredAccess | 4,
549                                   0,
550                                   &Privileges,
551                                   IoGetFileObjectGenericMapping(),
552                                   PreviousMode,
553                                   &GrantedAccess,
554                                   &IoStatus.Status);
555 
556     if (Privileges)
557     {
558         SeAppendPrivileges(AccessState, Privileges);
559         SeFreePrivileges(Privileges);
560     }
561 
562     if (AccessGranted)
563     {
564         AccessState->PreviouslyGrantedAccess |= GrantedAccess;
565         AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
566     }
567 
568     ObjectTypeName.Buffer = L"NamedPipe";
569     ObjectTypeName.Length = 18;
570     SeOpenObjectAuditAlarm(&ObjectTypeName,
571                            NULL,
572                            &FileObject->FileName,
573                            Fcb->SecurityDescriptor,
574                            AccessState,
575                            FALSE,
576                            AccessGranted,
577                            PreviousMode,
578                            &AccessState->GenerateOnClose);
579 
580     SeUnlockSubjectContext(SubjectSecurityContext);
581     if (!AccessGranted)
582     {
583         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
584         return IoStatus;
585     }
586 
587     if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
588     {
589         IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
590         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
591         return IoStatus;
592     }
593 
594     if (Disposition == FILE_CREATE)
595     {
596         IoStatus.Status = STATUS_ACCESS_DENIED;
597         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
598         return IoStatus;
599     }
600 
601     CheckShareAccess = 0;
602     if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
603     {
604         CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
605     }
606     else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
607     {
608         CheckShareAccess = FILE_SHARE_READ;
609     }
610     else if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
611     {
612         CheckShareAccess = FILE_SHARE_WRITE;
613     }
614 
615     if (CheckShareAccess != ShareAccess)
616     {
617         IoStatus.Status = STATUS_ACCESS_DENIED;
618         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
619         return IoStatus;
620     }
621 
622     IoStatus.Status = NpCreateCcb(Fcb,
623                                   FileObject,
624                                   FILE_PIPE_LISTENING_STATE,
625                                   Parameters->ReadMode & 0xFF,
626                                   Parameters->CompletionMode & 0xFF,
627                                   Parameters->InboundQuota,
628                                   Parameters->OutboundQuota,
629                                   &Ccb);
630     if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
631 
632     IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue,
633                                      &Fcb->FullName,
634                                      FALSE,
635                                      List);
636     if (!NT_SUCCESS(IoStatus.Status))
637     {
638         --Ccb->Fcb->CurrentInstances;
639         NpDeleteCcb(Ccb, List);
640         TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
641         return IoStatus;
642     }
643 
644     NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
645     Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
646     NpCheckForNotify(Fcb->ParentDcb, 0, List);
647 
648     IoStatus.Status = STATUS_SUCCESS;
649     IoStatus.Information = FILE_OPENED;
650     TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
651     return IoStatus;
652 }
653 
654 NTSTATUS
655 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,OUT PIO_STATUS_BLOCK IoStatus)656 NpCreateNewNamedPipe(IN PNP_DCB Dcb,
657                      IN PFILE_OBJECT FileObject,
658                      IN UNICODE_STRING PipeName,
659                      IN ACCESS_MASK DesiredAccess,
660                      IN PACCESS_STATE AccessState,
661                      IN USHORT Disposition,
662                      IN USHORT ShareAccess,
663                      IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
664                      IN PEPROCESS Process,
665                      IN PLIST_ENTRY List,
666                      OUT PIO_STATUS_BLOCK IoStatus)
667 {
668     NTSTATUS Status;
669     USHORT NamedPipeConfiguration;
670     PSECURITY_SUBJECT_CONTEXT SecurityContext;
671     PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor;
672     PNP_CCB Ccb;
673     PNP_FCB Fcb;
674     PAGED_CODE();
675     TRACE("Entered\n");
676 
677     if (!(Parameters->TimeoutSpecified) ||
678         !(Parameters->MaximumInstances) ||
679         (Parameters->DefaultTimeout.QuadPart >= 0))
680     {
681         Status = STATUS_INVALID_PARAMETER;
682         goto Quickie;
683     }
684 
685     if (Disposition == FILE_OPEN)
686     {
687         Status = STATUS_OBJECT_NAME_NOT_FOUND;
688         goto Quickie;
689     }
690 
691     if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE))
692     {
693         NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
694     }
695     else if (ShareAccess == FILE_SHARE_READ)
696     {
697         NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
698     }
699     else if (ShareAccess == FILE_SHARE_WRITE)
700     {
701         NamedPipeConfiguration = FILE_PIPE_INBOUND;
702     }
703     else
704     {
705         Status = STATUS_INVALID_PARAMETER;
706         goto Quickie;
707     }
708 
709     if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
710         Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE)
711     {
712         Status = STATUS_INVALID_PARAMETER;
713         goto Quickie;
714     }
715 
716     Status = NpCreateFcb(Dcb,
717                          &PipeName,
718                          Parameters->MaximumInstances,
719                          Parameters->DefaultTimeout,
720                          NamedPipeConfiguration,
721                          Parameters->NamedPipeType & 0xFFFF,
722                          &Fcb);
723     if (!NT_SUCCESS(Status)) goto Quickie;
724 
725     Status = NpCreateCcb(Fcb,
726                          FileObject,
727                          FILE_PIPE_LISTENING_STATE,
728                          Parameters->ReadMode & 0xFF,
729                          Parameters->CompletionMode & 0xFF,
730                          Parameters->InboundQuota,
731                          Parameters->OutboundQuota,
732                          &Ccb);
733     if (!NT_SUCCESS(Status))
734     {
735         NpDeleteFcb(Fcb, List);
736         goto Quickie;
737     }
738 
739     SecurityContext = &AccessState->SubjectSecurityContext;
740     SeLockSubjectContext(SecurityContext);
741 
742     Status = SeAssignSecurity(NULL,
743                               AccessState->SecurityDescriptor,
744                               &SecurityDescriptor,
745                               FALSE,
746                               SecurityContext,
747                               IoGetFileObjectGenericMapping(),
748                               PagedPool);
749     SeUnlockSubjectContext(SecurityContext);
750     if (!NT_SUCCESS(Status))
751     {
752         NpDeleteCcb(Ccb, List);
753         NpDeleteFcb(Fcb, List);
754         goto Quickie;
755     }
756 
757     Status = ObLogSecurityDescriptor(SecurityDescriptor,
758                                      &CachedSecurityDescriptor,
759                                      1);
760     ExFreePoolWithTag(SecurityDescriptor, 0);
761 
762     if (!NT_SUCCESS(Status))
763     {
764         NpDeleteCcb(Ccb, List);
765         NpDeleteFcb(Fcb, List);
766         goto Quickie;
767     }
768 
769     Fcb->SecurityDescriptor = CachedSecurityDescriptor;
770 
771     NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
772     Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
773 
774     NpCheckForNotify(Dcb, TRUE, List);
775 
776     IoStatus->Status = STATUS_SUCCESS;
777     IoStatus->Information = FILE_CREATED;
778 
779     TRACE("Leaving, STATUS_SUCCESS\n");
780     return STATUS_SUCCESS;
781 
782 Quickie:
783     TRACE("Leaving, Status = %lx\n", Status);
784     IoStatus->Information = 0;
785     IoStatus->Status = Status;
786     return Status;
787 }
788 
789 NTSTATUS
790 NTAPI
NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)791 NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
792                      IN PIRP Irp)
793 {
794     PIO_STACK_LOCATION IoStack;
795     PFILE_OBJECT FileObject;
796     PFILE_OBJECT RelatedFileObject;
797     USHORT Disposition, ShareAccess;
798     PEPROCESS Process;
799     LIST_ENTRY DeferredList;
800     UNICODE_STRING FileName;
801     PNP_FCB Fcb;
802     UNICODE_STRING Prefix;
803     PNAMED_PIPE_CREATE_PARAMETERS Parameters;
804     IO_STATUS_BLOCK IoStatus;
805     TRACE("Entered\n");
806 
807     InitializeListHead(&DeferredList);
808     Process = IoGetRequestorProcess(Irp);
809 
810     IoStack = IoGetCurrentIrpStackLocation(Irp);
811     FileObject = IoStack->FileObject;
812     RelatedFileObject = FileObject->RelatedFileObject;
813 
814     Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
815     ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
816     Parameters = IoStack->Parameters.CreatePipe.Parameters;
817 
818     FileName = FileObject->FileName;
819 
820     IoStatus.Information = 0;
821 
822     FsRtlEnterFileSystem();
823     NpAcquireExclusiveVcb();
824 
825     if (RelatedFileObject)
826     {
827         Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
828         if (!(Fcb) ||
829             (Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
830             (FileName.Length < sizeof(WCHAR)) ||
831             (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
832         {
833             IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
834             goto Quickie;
835         }
836 
837         IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
838                                                &FileName,
839                                                TRUE,
840                                                &Prefix,
841                                                &Fcb);
842         if (!NT_SUCCESS(IoStatus.Status))
843         {
844             goto Quickie;
845         }
846     }
847     else
848     {
849         if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) ||
850             FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
851         {
852             IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
853             goto Quickie;
854         }
855 
856         Fcb = NpFindPrefix(&FileName, 1, &Prefix);
857     }
858 
859     if (Prefix.Length)
860     {
861         if (Fcb->NodeType == NPFS_NTC_ROOT_DCB)
862         {
863             IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
864                                                    FileObject,
865                                                    FileName,
866                                                    IoStack->Parameters.CreatePipe.
867                                                    SecurityContext->DesiredAccess,
868                                                    IoStack->Parameters.CreatePipe.
869                                                    SecurityContext->AccessState,
870                                                    Disposition,
871                                                    ShareAccess,
872                                                    Parameters,
873                                                    Process,
874                                                    &DeferredList,
875                                                    &IoStatus);
876             goto Quickie;
877         }
878         else
879         {
880             IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
881             goto Quickie;
882         }
883     }
884 
885     if (Fcb->NodeType != NPFS_NTC_FCB)
886     {
887         IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
888         goto Quickie;
889     }
890 
891     IoStatus = NpCreateExistingNamedPipe(Fcb,
892                                          FileObject,
893                                          IoStack->Parameters.CreatePipe.
894                                          SecurityContext->DesiredAccess,
895                                          IoStack->Parameters.CreatePipe.
896                                          SecurityContext->AccessState,
897                                          IoStack->Flags &
898                                          SL_FORCE_ACCESS_CHECK ?
899                                          UserMode : Irp->RequestorMode,
900                                          Disposition,
901                                          ShareAccess,
902                                          Parameters,
903                                          Process,
904                                          &DeferredList);
905 
906 Quickie:
907     NpReleaseVcb();
908     NpCompleteDeferredIrps(&DeferredList);
909     FsRtlExitFileSystem();
910 
911     TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
912     Irp->IoStatus = IoStatus;
913     IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
914     return IoStatus.Status;
915 }
916 
917 /* EOF */
918