[NPFS]
[reactos.git] / reactos / 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 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
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.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
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.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 */