Sync with trunk rev.61910 to get latest improvements and bugfixes.
[reactos.git] / drivers / filesystems / npfs / create.c
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
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
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
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 = %lx\n", IoStatus);
100 return IoStatus;
101 }
102
103 IO_STATUS_BLOCK
104 NTAPI
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.Status = STATUS_SUCCESS;
126 IoStatus.Information = 0;
127 Privileges = NULL;
128
129 NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
130
131 SubjectSecurityContext = &AccessState->SubjectSecurityContext;
132 SeLockSubjectContext(SubjectSecurityContext);
133
134 AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
135 SubjectSecurityContext,
136 TRUE,
137 DesiredAccess & ~4,
138 0,
139 &Privileges,
140 IoGetFileObjectGenericMapping(),
141 PreviousMode,
142 &GrantedAccess,
143 &IoStatus.Status);
144
145 if (Privileges)
146 {
147 SeAppendPrivileges(AccessState, Privileges);
148 SeFreePrivileges(Privileges);
149 }
150
151 if (AccessGranted)
152 {
153 AccessState->PreviouslyGrantedAccess |= GrantedAccess;
154 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
155 }
156
157 ObjectTypeName.Buffer = L"NamedPipe";
158 ObjectTypeName.Length = 18;
159 SeOpenObjectAuditAlarm(&ObjectTypeName,
160 NULL,
161 &FileObject->FileName,
162 Fcb->SecurityDescriptor,
163 AccessState,
164 FALSE,
165 AccessGranted,
166 PreviousMode,
167 &AccessState->GenerateOnClose);
168 SeUnlockSubjectContext(SubjectSecurityContext);
169 if (!AccessGranted) return IoStatus;
170
171 if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) ||
172 ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)))
173 {
174 IoStatus.Status = STATUS_ACCESS_DENIED;
175 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
176 return IoStatus;
177 }
178
179 if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL;
180
181 ListHead = &Fcb->CcbList;
182 NextEntry = ListHead->Flink;
183 while (NextEntry != ListHead)
184 {
185 Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
186 if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
187
188 NextEntry = NextEntry->Flink;
189 }
190
191 if (NextEntry == ListHead)
192 {
193 IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
194 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
195 return IoStatus;
196 }
197
198 IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
199 if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
200
201 IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
202 if (!NT_SUCCESS(IoStatus.Status))
203 {
204 NpUninitializeSecurity(Ccb);
205 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
206 return IoStatus;
207 }
208
209 Ccb->ClientSession = NULL;
210 Ccb->Process = IoThreadToProcess(Thread);
211
212 IoStatus.Information = FILE_OPENED;
213 IoStatus.Status = STATUS_SUCCESS;
214 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
215 return IoStatus;
216 }
217
218 NTSTATUS
219 NTAPI
220 NpTranslateAlias(
221 PUNICODE_STRING PipeName)
222 {
223 WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
224 UNICODE_STRING UpcaseString;
225 ULONG Length;
226 PNPFS_ALIAS CurrentAlias;
227 NTSTATUS Status;
228 BOOLEAN BufferAllocated, BackSlash;
229 LONG Result;
230 PAGED_CODE();
231
232 /* Get the pipe name length and check for empty string */
233 Length = PipeName->Length;
234 if (Length == 0)
235 {
236 return STATUS_SUCCESS;
237 }
238
239 /* Check if the name starts with a path separator */
240 BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
241 if (BackSlash)
242 {
243 /* We are only interested in the part after the backslash */
244 Length -= sizeof(WCHAR);
245 }
246
247 /* Check if the length is within our indexed list bounds */
248 if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
249 (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
250 {
251 /* Length is within bounds, use the list by length */
252 CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
253 }
254 else
255 {
256 /* We use the generic list, search for an entry of the right size */
257 CurrentAlias = NpAliasList;
258 while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length))
259 {
260 /* Check if we went past the desired length */
261 if (CurrentAlias->Name.Length > Length)
262 {
263 /* In this case there is no matching alias, return success */
264 return STATUS_SUCCESS;
265 }
266
267 /* Go to the next alias in the list */
268 CurrentAlias = CurrentAlias->Next;
269 }
270 }
271
272 /* Did we find any alias? */
273 if (CurrentAlias == NULL)
274 {
275 /* Nothing found, no matching alias */
276 return STATUS_SUCCESS;
277 }
278
279 /* Check whether we can use our stack buffer */
280 if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))
281 {
282 /* Initialize the upcased string */
283 UpcaseString.Buffer = UpcaseBuffer;
284 UpcaseString.MaximumLength = sizeof(UpcaseBuffer);
285
286 /* Upcase the pipe name */
287 Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
288 NT_ASSERT(NT_SUCCESS(Status));
289 BufferAllocated = FALSE;
290 }
291 else
292 {
293 /* Upcase the pipe name, allocate the string buffer */
294 Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
295 if (!NT_SUCCESS(Status))
296 {
297 return Status;
298 }
299
300 BufferAllocated = TRUE;
301 }
302
303 /* Did the original name start with a backslash? */
304 if (BackSlash)
305 {
306 /* Skip it for the comparison */
307 UpcaseString.Buffer++;
308 UpcaseString.Length -= sizeof(WCHAR);
309 }
310
311 /* Make sure the length matches the "raw" length */
312 NT_ASSERT(UpcaseString.Length == Length);
313 NT_ASSERT(CurrentAlias->Name.Length == Length);
314
315 /* Loop while we have aliases */
316 do
317 {
318 /* Compare the names and check if they match */
319 Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
320 if (Result == 0)
321 {
322 /* The names match, use the target name */
323 *PipeName = *CurrentAlias->TargetName;
324
325 /* Did the original name start with a backslash? */
326 if (!BackSlash)
327 {
328 /* It didn't, so skip it in the target name as well */
329 PipeName->Buffer++;
330 PipeName->Length -= sizeof(WCHAR);
331 }
332 break;
333 }
334
335 /* Check if we went past all string candidates */
336 if (Result < 0)
337 {
338 /* Nothing found, we're done */
339 break;
340 }
341
342 /* Go to the next alias */
343 CurrentAlias = CurrentAlias->Next;
344
345 /* Keep looping while we have aliases of the right length */
346 } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
347
348 /* Did we allocate a buffer? */
349 if (BufferAllocated)
350 {
351 /* Free the allocated buffer */
352 ASSERT(UpcaseString.Buffer != UpcaseBuffer);
353 RtlFreeUnicodeString(&UpcaseString);
354 }
355
356 return STATUS_SUCCESS;
357 }
358
359 NTSTATUS
360 NTAPI
361 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
362 IN PIRP Irp)
363 {
364 IO_STATUS_BLOCK IoStatus;
365 PEXTENDED_IO_STACK_LOCATION IoStack;
366 UNICODE_STRING FileName;
367 PFILE_OBJECT FileObject;
368 PFILE_OBJECT RelatedFileObject;
369 NODE_TYPE_CODE Type;
370 PNP_CCB Ccb;
371 PNP_FCB Fcb;
372 PNP_DCB Dcb;
373 ACCESS_MASK DesiredAccess;
374 LIST_ENTRY DeferredList;
375 UNICODE_STRING Prefix;
376 NTSTATUS Status;
377 TRACE("Entered\n");
378
379 InitializeListHead(&DeferredList);
380 IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
381 FileObject = IoStack->FileObject;
382 RelatedFileObject = FileObject->RelatedFileObject;
383 FileName = FileObject->FileName;
384 DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
385
386 IoStatus.Information = 0;
387 IoStatus.Status = STATUS_SUCCESS;
388
389 FsRtlEnterFileSystem();
390 ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
391
392 if (RelatedFileObject)
393 {
394 Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
395 }
396 else
397 {
398 Type = 0;
399 Fcb = NULL;
400 Ccb = NULL;
401 }
402
403 if (FileName.Length)
404 {
405 if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
406 (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
407 !(RelatedFileObject))
408 {
409 IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
410 FileObject,
411 DesiredAccess,
412 &DeferredList);
413 goto Quickie;
414 }
415 }
416 else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
417 {
418 IoStatus = NpOpenNamedPipeFileSystem(FileObject,
419 DesiredAccess);
420 goto Quickie;
421 }
422 else if (Type == NPFS_NTC_ROOT_DCB)
423 {
424 IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
425 FileObject,
426 DesiredAccess,
427 &DeferredList);
428 goto Quickie;
429 }
430
431 Status = NpTranslateAlias(&FileName);
432 if (!NT_SUCCESS(Status)) goto Quickie;
433
434 if (RelatedFileObject)
435 {
436 if (Type == NPFS_NTC_ROOT_DCB)
437 {
438 Dcb = (PNP_DCB)Ccb;
439 IoStatus.Status = NpFindRelativePrefix(Dcb,
440 &FileName,
441 1,
442 &Prefix,
443 &Fcb);
444 if (!NT_SUCCESS(IoStatus.Status))
445 {
446 goto Quickie;
447 }
448 }
449 else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
450 {
451 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
452 goto Quickie;
453 }
454 else
455 {
456 Prefix.Length = 0;
457 }
458 }
459 else
460 {
461 if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
462 (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
463 {
464 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
465 goto Quickie;
466 }
467
468 Fcb = NpFindPrefix(&FileName, TRUE, &Prefix);
469 }
470
471 if (Prefix.Length)
472 {
473 IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
474 STATUS_OBJECT_NAME_NOT_FOUND :
475 STATUS_OBJECT_NAME_INVALID;
476 goto Quickie;
477 }
478
479 if (Fcb->NodeType != NPFS_NTC_FCB)
480 {
481 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
482 goto Quickie;
483 }
484
485 if (!Fcb->ServerOpenCount)
486 {
487 IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
488 goto Quickie;
489 }
490
491 IoStatus = NpCreateClientEnd(Fcb,
492 FileObject,
493 DesiredAccess,
494 IoStack->Parameters.CreatePipe.
495 SecurityContext->SecurityQos,
496 IoStack->Parameters.CreatePipe.
497 SecurityContext->AccessState,
498 IoStack->Flags &
499 SL_FORCE_ACCESS_CHECK ?
500 UserMode : Irp->RequestorMode,
501 Irp->Tail.Overlay.Thread,
502 &DeferredList);
503
504 Quickie:
505 ExReleaseResourceLite(&NpVcb->Lock);
506 NpCompleteDeferredIrps(&DeferredList);
507 FsRtlExitFileSystem();
508
509 Irp->IoStatus = IoStatus;
510 IoCompleteRequest(Irp, IO_NO_INCREMENT);
511 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
512 return IoStatus.Status;
513 }
514
515 IO_STATUS_BLOCK
516 NTAPI
517 NpCreateExistingNamedPipe(IN PNP_FCB Fcb,
518 IN PFILE_OBJECT FileObject,
519 IN ACCESS_MASK DesiredAccess,
520 IN PACCESS_STATE AccessState,
521 IN KPROCESSOR_MODE PreviousMode,
522 IN ULONG Disposition,
523 IN ULONG ShareAccess,
524 IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
525 IN PEPROCESS Process,
526 OUT PLIST_ENTRY List)
527 {
528 PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
529 IO_STATUS_BLOCK IoStatus;
530 UNICODE_STRING ObjectTypeName;
531 ACCESS_MASK GrantedAccess;
532 PNP_CCB Ccb;
533 PPRIVILEGE_SET Privileges;
534 USHORT NamedPipeConfiguration, CheckShareAccess;
535 BOOLEAN AccessGranted;
536 PAGED_CODE();
537 TRACE("Entered\n");
538
539 Privileges = NULL;
540
541 NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
542
543 SubjectSecurityContext = &AccessState->SubjectSecurityContext;
544 SeLockSubjectContext(SubjectSecurityContext);
545
546 AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
547 SubjectSecurityContext,
548 TRUE,
549 DesiredAccess | 4,
550 0,
551 &Privileges,
552 IoGetFileObjectGenericMapping(),
553 PreviousMode,
554 &GrantedAccess,
555 &IoStatus.Status);
556
557 if (Privileges)
558 {
559 SeAppendPrivileges(AccessState, Privileges);
560 SeFreePrivileges(Privileges);
561 }
562
563 if (AccessGranted)
564 {
565 AccessState->PreviouslyGrantedAccess |= GrantedAccess;
566 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000);
567 }
568
569 ObjectTypeName.Buffer = L"NamedPipe";
570 ObjectTypeName.Length = 18;
571 SeOpenObjectAuditAlarm(&ObjectTypeName,
572 NULL,
573 &FileObject->FileName,
574 Fcb->SecurityDescriptor,
575 AccessState,
576 FALSE,
577 AccessGranted,
578 PreviousMode,
579 &AccessState->GenerateOnClose);
580
581 SeUnlockSubjectContext(SubjectSecurityContext);
582 if (!AccessGranted)
583 {
584 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
585 return IoStatus;
586 }
587
588 if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
589 {
590 IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
591 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
592 return IoStatus;
593 }
594
595 if (Disposition == FILE_CREATE)
596 {
597 IoStatus.Status = STATUS_ACCESS_DENIED;
598 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
599 return IoStatus;
600 }
601
602 CheckShareAccess = 0;
603 if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
604 {
605 CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
606 }
607 else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND)
608 {
609 CheckShareAccess = FILE_SHARE_READ;
610 }
611 else if (NamedPipeConfiguration == FILE_PIPE_INBOUND)
612 {
613 CheckShareAccess = FILE_SHARE_WRITE;
614 }
615
616 if (CheckShareAccess != ShareAccess)
617 {
618 IoStatus.Status = STATUS_ACCESS_DENIED;
619 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
620 return IoStatus;
621 }
622
623 IoStatus.Status = NpCreateCcb(Fcb,
624 FileObject,
625 FILE_PIPE_LISTENING_STATE,
626 Parameters->ReadMode & 0xFF,
627 Parameters->CompletionMode & 0xFF,
628 Parameters->InboundQuota,
629 Parameters->OutboundQuota,
630 &Ccb);
631 if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
632
633 IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue,
634 &Fcb->FullName,
635 FALSE,
636 List);
637 if (!NT_SUCCESS(IoStatus.Status))
638 {
639 --Ccb->Fcb->CurrentInstances;
640 NpDeleteCcb(Ccb, List);
641 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
642 return IoStatus;
643 }
644
645 NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
646 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
647 NpCheckForNotify(Fcb->ParentDcb, 0, List);
648
649 IoStatus.Status = STATUS_SUCCESS;
650 IoStatus.Information = 1;
651 TRACE("Leaving, IoStatus = %lx\n", IoStatus);
652 return IoStatus;
653 }
654
655 NTSTATUS
656 NTAPI
657 NpCreateNewNamedPipe(IN PNP_DCB Dcb,
658 IN PFILE_OBJECT FileObject,
659 IN UNICODE_STRING PipeName,
660 IN ACCESS_MASK DesiredAccess,
661 IN PACCESS_STATE AccessState,
662 IN USHORT Disposition,
663 IN USHORT ShareAccess,
664 IN PNAMED_PIPE_CREATE_PARAMETERS Parameters,
665 IN PEPROCESS Process,
666 IN PLIST_ENTRY List,
667 IN PIO_STATUS_BLOCK IoStatus)
668 {
669 NTSTATUS Status;
670 USHORT NamedPipeConfiguration;
671 PSECURITY_SUBJECT_CONTEXT SecurityContext;
672 PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor;
673 PNP_CCB Ccb;
674 PNP_FCB Fcb;
675 PAGED_CODE();
676 TRACE("Entered\n");
677
678 if (!(Parameters->TimeoutSpecified) ||
679 !(Parameters->MaximumInstances) ||
680 (Parameters->DefaultTimeout.HighPart >= 0))
681 {
682 Status = STATUS_INVALID_PARAMETER;
683 goto Quickie;
684 }
685
686 if (Disposition == FILE_OPEN)
687 {
688 Status = STATUS_OBJECT_NAME_NOT_FOUND;
689 goto Quickie;
690 }
691
692 if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE))
693 {
694 NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX;
695 }
696 else if (ShareAccess == FILE_SHARE_READ)
697 {
698 NamedPipeConfiguration = FILE_PIPE_OUTBOUND;
699 }
700 else if (ShareAccess == FILE_SHARE_WRITE)
701 {
702 NamedPipeConfiguration = FILE_PIPE_INBOUND;
703 }
704 else
705 {
706 Status = STATUS_INVALID_PARAMETER;
707 goto Quickie;
708 }
709
710 if (!Parameters->NamedPipeType && Parameters->ReadMode == 1)
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(&AccessState->SubjectSecurityContext);
741
742 Status = SeAssignSecurity(0,
743 AccessState->SecurityDescriptor,
744 &SecurityDescriptor,
745 0,
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 ExFreePool(SecurityDescriptor);
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
791 NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
792 IN PIRP Irp)
793 {
794 PEXTENDED_IO_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 = (PEXTENDED_IO_STACK_LOCATION) 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.Status = STATUS_SUCCESS;
821 IoStatus.Information = 0;
822
823 FsRtlEnterFileSystem();
824 NpAcquireExclusiveVcb();
825
826 if (RelatedFileObject)
827 {
828 Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
829 if (!(Fcb) ||
830 (Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
831 (FileName.Length < sizeof(WCHAR)) ||
832 (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
833 {
834 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
835 goto Quickie;
836 }
837
838 IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
839 &FileName,
840 TRUE,
841 &Prefix,
842 &Fcb);
843 if (!NT_SUCCESS(IoStatus.Status))
844 {
845 goto Quickie;
846 }
847 }
848 else
849 {
850 if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) ||
851 FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
852 {
853 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
854 goto Quickie;
855 }
856
857 Fcb = NpFindPrefix(&FileName, TRUE, &Prefix);
858 }
859
860 if (Prefix.Length)
861 {
862 if (Fcb->NodeType == NPFS_NTC_ROOT_DCB)
863 {
864 IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
865 FileObject,
866 FileName,
867 IoStack->Parameters.CreatePipe.
868 SecurityContext->DesiredAccess,
869 IoStack->Parameters.CreatePipe.
870 SecurityContext->AccessState,
871 Disposition,
872 ShareAccess,
873 Parameters,
874 Process,
875 &DeferredList,
876 &IoStatus);
877 goto Quickie;
878 }
879 else
880 {
881 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
882 goto Quickie;
883 }
884 }
885
886 if (Fcb->NodeType != NPFS_NTC_FCB)
887 {
888 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
889 goto Quickie;
890 }
891
892 IoStatus = NpCreateExistingNamedPipe(Fcb,
893 FileObject,
894 IoStack->Parameters.CreatePipe.
895 SecurityContext->DesiredAccess,
896 IoStack->Parameters.CreatePipe.
897 SecurityContext->AccessState,
898 IoStack->Flags &
899 SL_FORCE_ACCESS_CHECK ?
900 UserMode : Irp->RequestorMode,
901 Disposition,
902 ShareAccess,
903 Parameters,
904 Process,
905 &DeferredList);
906
907 Quickie:
908 NpReleaseVcb();
909 NpCompleteDeferredIrps(&DeferredList);
910 FsRtlExitFileSystem();
911
912 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
913 Irp->IoStatus = IoStatus;
914 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
915 return IoStatus.Status;
916 }
917
918 /* EOF */