Sync with trunk r63786.
[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.Status = %lx\n", IoStatus.Status);
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.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
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
360 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
361 IN PIRP Irp)
362 {
363 IO_STATUS_BLOCK IoStatus;
364 PEXTENDED_IO_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 = (PEXTENDED_IO_STACK_LOCATION)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 ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
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, TRUE, &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 ExReleaseResourceLite(&NpVcb->Lock);
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
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 | 0x2000000);
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
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.HighPart >= 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 && Parameters->ReadMode == 1)
710 {
711 Status = STATUS_INVALID_PARAMETER;
712 goto Quickie;
713 }
714
715 Status = NpCreateFcb(Dcb,
716 &PipeName,
717 Parameters->MaximumInstances,
718 Parameters->DefaultTimeout,
719 NamedPipeConfiguration,
720 Parameters->NamedPipeType & 0xFFFF,
721 &Fcb);
722 if (!NT_SUCCESS(Status)) goto Quickie;
723
724 Status = NpCreateCcb(Fcb,
725 FileObject,
726 FILE_PIPE_LISTENING_STATE,
727 Parameters->ReadMode & 0xFF,
728 Parameters->CompletionMode & 0xFF,
729 Parameters->InboundQuota,
730 Parameters->OutboundQuota,
731 &Ccb);
732 if (!NT_SUCCESS(Status))
733 {
734 NpDeleteFcb(Fcb, List);
735 goto Quickie;
736 }
737
738 SecurityContext = &AccessState->SubjectSecurityContext;
739 SeLockSubjectContext(&AccessState->SubjectSecurityContext);
740
741 Status = SeAssignSecurity(0,
742 AccessState->SecurityDescriptor,
743 &SecurityDescriptor,
744 0,
745 SecurityContext,
746 IoGetFileObjectGenericMapping(),
747 PagedPool);
748 SeUnlockSubjectContext(SecurityContext);
749 if (!NT_SUCCESS(Status))
750 {
751 NpDeleteCcb(Ccb, List);
752 NpDeleteFcb(Fcb, List);
753 goto Quickie;
754 }
755
756 Status = ObLogSecurityDescriptor(SecurityDescriptor,
757 &CachedSecurityDescriptor,
758 1);
759 ExFreePool(SecurityDescriptor);
760
761 if (!NT_SUCCESS(Status))
762 {
763 NpDeleteCcb(Ccb, List);
764 NpDeleteFcb(Fcb, List);
765 goto Quickie;
766 }
767
768 Fcb->SecurityDescriptor = CachedSecurityDescriptor;
769
770 NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
771 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
772
773 NpCheckForNotify(Dcb, TRUE, List);
774
775 IoStatus->Status = STATUS_SUCCESS;
776 IoStatus->Information = FILE_CREATED;
777
778 TRACE("Leaving, STATUS_SUCCESS\n");
779 return STATUS_SUCCESS;
780
781 Quickie:
782 TRACE("Leaving, Status = %lx\n", Status);
783 IoStatus->Information = 0;
784 IoStatus->Status = Status;
785 return Status;
786 }
787
788 NTSTATUS
789 NTAPI
790 NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
791 IN PIRP Irp)
792 {
793 PEXTENDED_IO_STACK_LOCATION IoStack;
794 PFILE_OBJECT FileObject;
795 PFILE_OBJECT RelatedFileObject;
796 USHORT Disposition, ShareAccess;
797 PEPROCESS Process;
798 LIST_ENTRY DeferredList;
799 UNICODE_STRING FileName;
800 PNP_FCB Fcb;
801 UNICODE_STRING Prefix;
802 PNAMED_PIPE_CREATE_PARAMETERS Parameters;
803 IO_STATUS_BLOCK IoStatus;
804 TRACE("Entered\n");
805
806 InitializeListHead(&DeferredList);
807 Process = IoGetRequestorProcess(Irp);
808
809 IoStack = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation(Irp);
810 FileObject = IoStack->FileObject;
811 RelatedFileObject = FileObject->RelatedFileObject;
812
813 Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
814 ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
815 Parameters = IoStack->Parameters.CreatePipe.Parameters;
816
817 FileName = FileObject->FileName;
818
819 IoStatus.Information = 0;
820
821 FsRtlEnterFileSystem();
822 NpAcquireExclusiveVcb();
823
824 if (RelatedFileObject)
825 {
826 Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1);
827 if (!(Fcb) ||
828 (Fcb->NodeType != NPFS_NTC_ROOT_DCB) ||
829 (FileName.Length < sizeof(WCHAR)) ||
830 (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
831 {
832 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
833 goto Quickie;
834 }
835
836 IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
837 &FileName,
838 TRUE,
839 &Prefix,
840 &Fcb);
841 if (!NT_SUCCESS(IoStatus.Status))
842 {
843 goto Quickie;
844 }
845 }
846 else
847 {
848 if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) ||
849 FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)
850 {
851 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
852 goto Quickie;
853 }
854
855 Fcb = NpFindPrefix(&FileName, TRUE, &Prefix);
856 }
857
858 if (Prefix.Length)
859 {
860 if (Fcb->NodeType == NPFS_NTC_ROOT_DCB)
861 {
862 IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb,
863 FileObject,
864 FileName,
865 IoStack->Parameters.CreatePipe.
866 SecurityContext->DesiredAccess,
867 IoStack->Parameters.CreatePipe.
868 SecurityContext->AccessState,
869 Disposition,
870 ShareAccess,
871 Parameters,
872 Process,
873 &DeferredList,
874 &IoStatus);
875 goto Quickie;
876 }
877 else
878 {
879 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
880 goto Quickie;
881 }
882 }
883
884 if (Fcb->NodeType != NPFS_NTC_FCB)
885 {
886 IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
887 goto Quickie;
888 }
889
890 IoStatus = NpCreateExistingNamedPipe(Fcb,
891 FileObject,
892 IoStack->Parameters.CreatePipe.
893 SecurityContext->DesiredAccess,
894 IoStack->Parameters.CreatePipe.
895 SecurityContext->AccessState,
896 IoStack->Flags &
897 SL_FORCE_ACCESS_CHECK ?
898 UserMode : Irp->RequestorMode,
899 Disposition,
900 ShareAccess,
901 Parameters,
902 Process,
903 &DeferredList);
904
905 Quickie:
906 NpReleaseVcb();
907 NpCompleteDeferredIrps(&DeferredList);
908 FsRtlExitFileSystem();
909
910 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
911 Irp->IoStatus = IoStatus;
912 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
913 return IoStatus.Status;
914 }
915
916 /* EOF */