Windows: Deny writes/truncation to files w RO attr
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCreate.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSCreate.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSCreate
43 //
44 // Description:
45 //
46 //      This function is the dispatch handler for the IRP_MJ_CREATE requests. It makes the determination to
47 //      which interface this request is destined.
48 //
49 // Return:
50 //
51 //      A status is returned for the function. The Irp completion processing is handled in the specific
52 //      interface handler.
53 //
54
55 NTSTATUS
56 AFSCreate( IN PDEVICE_OBJECT LibDeviceObject,
57            IN PIRP Irp)
58 {
59     UNREFERENCED_PARAMETER(LibDeviceObject);
60     NTSTATUS ntStatus = STATUS_SUCCESS;
61     IO_STACK_LOCATION  *pIrpSp;
62     FILE_OBJECT        *pFileObject = NULL;
63
64     __try
65     {
66
67         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
68         pFileObject = pIrpSp->FileObject;
69
70         if( pFileObject == NULL ||
71             pFileObject->FileName.Buffer == NULL)
72         {
73
74             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
75                           AFS_TRACE_LEVEL_VERBOSE,
76                           "AFSCreate (%p) Processing control device open request\n",
77                           Irp));
78
79             ntStatus = AFSControlDeviceCreate( Irp);
80
81             try_return( ntStatus);
82         }
83
84         if( AFSRDRDeviceObject == NULL)
85         {
86
87             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
88                           AFS_TRACE_LEVEL_VERBOSE,
89                           "AFSCreate (%p) Invalid request to open before library is initialized\n",
90                           Irp));
91
92             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
93         }
94
95         ntStatus = AFSCommonCreate( AFSRDRDeviceObject,
96                                     Irp);
97
98 try_exit:
99
100         NOTHING;
101     }
102     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) )
103     {
104
105         AFSDbgTrace(( 0,
106                       0,
107                       "EXCEPTION - AFSCreate\n"));
108
109         ntStatus = STATUS_ACCESS_DENIED;
110
111         AFSDumpTraceFilesFnc();
112     }
113
114     //
115     // Complete the request
116     //
117
118     AFSCompleteRequest( Irp,
119                           ntStatus);
120
121     return ntStatus;
122 }
123
124 NTSTATUS
125 AFSCommonCreate( IN PDEVICE_OBJECT DeviceObject,
126                  IN PIRP Irp)
127 {
128
129     NTSTATUS            ntStatus = STATUS_SUCCESS;
130     UNICODE_STRING      uniFileName;
131     ULONG               ulCreateDisposition = 0;
132     ULONG               ulOptions = 0;
133     BOOLEAN             bNoIntermediateBuffering = FALSE;
134     FILE_OBJECT        *pFileObject = NULL;
135     IO_STACK_LOCATION  *pIrpSp;
136     AFSFcb             *pFcb = NULL;
137     AFSCcb             *pCcb = NULL;
138     AFSDeviceExt       *pDeviceExt = NULL;
139     BOOLEAN             bOpenTargetDirectory = FALSE, bReleaseVolume = FALSE;
140     PACCESS_MASK        pDesiredAccess = NULL;
141     UNICODE_STRING      uniComponentName, uniRootFileName, uniParsedFileName;
142     UNICODE_STRING      uniSubstitutedPathName;
143     UNICODE_STRING      uniRelativeName;
144     AFSNameArrayHdr    *pNameArray = NULL;
145     AFSVolumeCB        *pVolumeCB = NULL;
146     LONG                VolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
147     AFSVolumeCB        *pNewVolumeCB = NULL;
148     LONG                NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
149     AFSDirectoryCB     *pParentDirectoryCB = NULL, *pDirectoryCB = NULL;
150     AFSDirectoryCB     *pNewParentDirectoryCB = NULL;
151     BOOLEAN             bReleaseParentDir = FALSE, bReleaseDir = FALSE;
152     ULONG               ulParseFlags = 0;
153     GUID                stAuthGroup = {0};
154     ULONG               ulNameProcessingFlags = 0;
155     BOOLEAN             bOpenedReparsePoint = FALSE;
156     LONG                lCount;
157
158     __Enter
159     {
160
161         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
162         pDeviceExt = (AFSDeviceExt *)DeviceObject->DeviceExtension;
163         ulCreateDisposition = (pIrpSp->Parameters.Create.Options >> 24) & 0x000000ff;
164         ulOptions = pIrpSp->Parameters.Create.Options;
165         bNoIntermediateBuffering = BooleanFlagOn( ulOptions, FILE_NO_INTERMEDIATE_BUFFERING);
166         bOpenTargetDirectory = BooleanFlagOn( pIrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
167         pFileObject = pIrpSp->FileObject;
168         pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
169
170         uniFileName.Length = uniFileName.MaximumLength = 0;
171         uniFileName.Buffer = NULL;
172
173         uniRootFileName.Length = uniRootFileName.MaximumLength = 0;
174         uniRootFileName.Buffer = NULL;
175
176         uniParsedFileName.Length = uniParsedFileName.MaximumLength = 0;
177         uniParsedFileName.Buffer = NULL;
178
179         uniSubstitutedPathName.Buffer = NULL;
180         uniSubstitutedPathName.Length = 0;
181
182         uniRelativeName.Buffer = NULL;
183         uniRelativeName.Length = 0;
184
185         if( AFSGlobalRoot == NULL)
186         {
187             try_return( ntStatus = STATUS_DEVICE_NOT_READY);
188         }
189
190         RtlZeroMemory( &stAuthGroup,
191                        sizeof( GUID));
192
193         AFSRetrieveAuthGroupFnc( (ULONGLONG)PsGetCurrentProcessId(),
194                                  (ULONGLONG)PsGetCurrentThreadId(),
195                                   &stAuthGroup);
196
197         //
198         // If we are in shutdown mode then fail the request
199         //
200
201         if( BooleanFlagOn( pDeviceExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN))
202         {
203
204             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
205                           AFS_TRACE_LEVEL_WARNING,
206                           "AFSCommonCreate (%p) Open request after shutdown\n",
207                           Irp));
208
209             try_return( ntStatus = STATUS_TOO_LATE);
210         }
211
212         if( !BooleanFlagOn( AFSGlobalRoot->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
213         {
214
215             ntStatus = AFSEnumerateGlobalRoot( &stAuthGroup);
216
217             if( !NT_SUCCESS( ntStatus))
218             {
219
220                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
221                               AFS_TRACE_LEVEL_ERROR,
222                               "AFSCommonCreate Failed to enumerate global root Status %08lX\n",
223                               ntStatus));
224
225                 try_return( ntStatus);
226             }
227         }
228
229         //
230         // Go and parse the name for processing.
231         // If ulParseFlags is returned with AFS_PARSE_FLAG_FREE_FILE_BUFFER set,
232         // then we are responsible for releasing the uniRootFileName.Buffer.
233         //
234
235         ntStatus = AFSParseName( Irp,
236                                  &stAuthGroup,
237                                  &uniFileName,
238                                  &uniParsedFileName,
239                                  &uniRootFileName,
240                                  &ulParseFlags,
241                                  &pVolumeCB,
242                                  &pParentDirectoryCB,
243                                  &pNameArray);
244
245         if( !NT_SUCCESS( ntStatus))
246         {
247
248             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
249                           uniFileName.Length > 0 ? AFS_TRACE_LEVEL_ERROR : AFS_TRACE_LEVEL_VERBOSE,
250                           "AFSCommonCreate (%p) Failed to parse name \"%wZ\" Status %08lX\n",
251                           Irp,
252                           &uniFileName,
253                           ntStatus));
254
255             try_return( ntStatus);
256         }
257
258         //
259         // Check for STATUS_REPARSE
260         //
261
262         if( ntStatus == STATUS_REPARSE)
263         {
264
265             //
266             // Update the information and return
267             //
268
269             Irp->IoStatus.Information = IO_REPARSE;
270
271             try_return( ntStatus);
272         }
273
274         if ( pParentDirectoryCB != NULL)
275         {
276
277             bReleaseParentDir = TRUE;
278         }
279
280         //
281         // If the returned volume cb is NULL then we are dealing with the \\Server\GlobalRoot
282         // name
283         //
284
285         if( pVolumeCB == NULL)
286         {
287
288             //
289             // Remove any leading or trailing slashes
290             //
291
292             if( uniFileName.Length >= sizeof( WCHAR) &&
293                 uniFileName.Buffer[ (uniFileName.Length/sizeof( WCHAR)) - 1] == L'\\')
294             {
295
296                 uniFileName.Length -= sizeof( WCHAR);
297             }
298
299             if( uniFileName.Length >= sizeof( WCHAR) &&
300                 uniFileName.Buffer[ 0] == L'\\')
301             {
302
303                 uniFileName.Buffer = &uniFileName.Buffer[ 1];
304
305                 uniFileName.Length -= sizeof( WCHAR);
306             }
307
308             //
309             // If there is a remaining portion returned for this request then
310             // check if it is for the PIOCtl interface
311             //
312
313             if( uniFileName.Length > 0)
314             {
315
316                 //
317                 // We don't accept any other opens off of the AFS Root
318                 //
319
320                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
321
322                 //
323                 // If this is an open on "_._AFS_IOCTL_._" then perform handling on it accordingly
324                 //
325
326                 if( RtlCompareUnicodeString( &AFSPIOCtlName,
327                                              &uniFileName,
328                                              TRUE) == 0)
329                 {
330
331                     //
332                     // AFSOpenIOCtlFcb does not free a DirOpenReferenceCount for
333                     // AFSGlobalRoot->DirectoryCB.
334                     //
335
336                     ntStatus = AFSOpenIOCtlFcb( Irp,
337                                                 &stAuthGroup,
338                                                 AFSGlobalRoot->DirectoryCB,
339                                                 &pFcb,
340                                                 &pCcb);
341
342                     if( !NT_SUCCESS( ntStatus))
343                     {
344
345                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
346                                       AFS_TRACE_LEVEL_ERROR,
347                                       "AFSCommonCreate Failed to open root IOCtl Fcb Status %08lX\n",
348                                       ntStatus));
349                     }
350                 }
351                 else if( pParentDirectoryCB != NULL)
352                 {
353
354                     if( pParentDirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_SPECIAL_SHARE_NAME)
355                     {
356
357                         ntStatus = AFSOpenSpecialShareFcb( Irp,
358                                                            &stAuthGroup,
359                                                            pParentDirectoryCB,
360                                                            &pFcb,
361                                                            &pCcb);
362
363                         if( !NT_SUCCESS( ntStatus))
364                         {
365
366                             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
367                                           AFS_TRACE_LEVEL_ERROR,
368                                           "AFSCommonCreate Failed to open special share Fcb Status %08lX\n",
369                                           ntStatus));
370                         }
371                     }
372                 }
373
374                 try_return( ntStatus);
375             }
376
377             ntStatus = AFSOpenAFSRoot( Irp,
378                                        &pFcb,
379                                        &pCcb);
380
381             if( !NT_SUCCESS( ntStatus))
382             {
383
384                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
385                               AFS_TRACE_LEVEL_ERROR,
386                               "AFSCommonCreate Failed to open root Status %08lX\n",
387                               ntStatus));
388             }
389
390             try_return( ntStatus);
391         }
392
393         //
394         // We have a reference on the root volume
395         //
396
397         VolumeReferenceReason = AFS_VOLUME_REFERENCE_PARSE_NAME;
398
399         bReleaseVolume = TRUE;
400
401         //
402         // Attempt to locate the node in the name tree if this is not a target
403         // open and the target is not the root
404         //
405
406         uniComponentName.Length = 0;
407         uniComponentName.Buffer = NULL;
408
409         if( uniFileName.Length > sizeof( WCHAR) ||
410             uniFileName.Buffer[ 0] != L'\\')
411         {
412
413             if( !AFSValidNameFormat( &uniFileName))
414             {
415
416                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
417
418                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
419                               AFS_TRACE_LEVEL_VERBOSE,
420                               "AFSCommonCreate (%p) Invalid name %wZ Status %08lX\n",
421                               Irp,
422                               &uniFileName,
423                               ntStatus));
424
425                 try_return( ntStatus);
426             }
427
428
429             if ( !AFSIgnoreReparsePointToFile() ||
430                  !BooleanFlagOn( ulOptions, FILE_OPEN_REPARSE_POINT))
431             {
432                 //
433                 // If there is no ReparsePointPolicy then the FILE_OPEN_REPARSE_POINT
434                 // flag is applied if it is set.
435                 //
436                 // If the FILE_OPEN_REPARSE_POINT flag is not set, then there is
437                 // no extra work to be done in any case.  Use a single pass evaluation.
438                 //
439
440                 ulNameProcessingFlags = AFS_LOCATE_FLAGS_SUBSTITUTE_NAME;
441
442                 //
443                 // Opening a reparse point directly?
444                 //
445
446                 if( BooleanFlagOn( ulOptions, FILE_OPEN_REPARSE_POINT))
447                 {
448                     ulNameProcessingFlags |= (AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
449                                                AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL |
450                                                AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL);
451                 }
452
453                 uniSubstitutedPathName = uniRootFileName;
454
455                 ntStatus = AFSLocateNameEntry( &stAuthGroup,
456                                                pFileObject,
457                                                &uniRootFileName,
458                                                &uniParsedFileName,
459                                                pNameArray,
460                                                ulNameProcessingFlags,
461                                                pVolumeCB,
462                                                pParentDirectoryCB,
463                                                &pNewVolumeCB,
464                                                &NewVolumeReferenceReason,
465                                                &pNewParentDirectoryCB,
466                                                &pDirectoryCB,
467                                                &uniComponentName);
468
469                 if ( pNewVolumeCB != NULL)
470                 {
471
472                     //
473                     // AFSLocateNameEntry returns pNewVolumeCB with a reference held
474                     // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
475                     // the reference on pVolumeCB that was held prior to the call.
476                     // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
477                     // will be released second.
478                     //
479
480                     lCount = AFSVolumeDecrement( pVolumeCB,
481                                                  VolumeReferenceReason);
482
483                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
484                                   AFS_TRACE_LEVEL_VERBOSE,
485                                   "AFSCommonCreate Decrement count on volume %p Reason %u Cnt %d\n",
486                                   pVolumeCB,
487                                   VolumeReferenceReason,
488                                   lCount));
489
490                     pVolumeCB = pNewVolumeCB;
491
492                     pNewVolumeCB = NULL;
493
494                     VolumeReferenceReason = NewVolumeReferenceReason;
495
496                     NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
497
498                     bReleaseVolume = (pVolumeCB != NULL);
499                 }
500
501                 //
502                 // AFSLocateNameEntry does not alter the reference count of
503                 // pParentDirectoryCB and it returns pNewParentDirectoryCB with
504                 // a reference held.
505                 //
506
507                 if ( bReleaseParentDir)
508                 {
509
510                     lCount = InterlockedDecrement( &pParentDirectoryCB->DirOpenReferenceCount);
511
512                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
513                                   AFS_TRACE_LEVEL_VERBOSE,
514                                   "AFSCommonCreate DecrementX count on %wZ DE %p Ccb %p Cnt %d\n",
515                                   &pParentDirectoryCB->NameInformation.FileName,
516                                   pParentDirectoryCB,
517                                   pCcb,
518                                   lCount));
519                 }
520
521                 pParentDirectoryCB = pNewParentDirectoryCB;
522
523                 pNewParentDirectoryCB = NULL;
524
525                 bReleaseParentDir = (pParentDirectoryCB != NULL);
526
527                 if ( pDirectoryCB)
528                 {
529
530                     bReleaseDir = TRUE;
531                 }
532
533                 if( !NT_SUCCESS( ntStatus) &&
534                     ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
535                 {
536
537                     if ( uniSubstitutedPathName.Buffer == uniRootFileName.Buffer)
538                     {
539                         uniSubstitutedPathName.Buffer = NULL;
540                     }
541
542                     //
543                     // AFSLocateNameEntry released the Parent while walking the
544                     // branch
545                     //
546
547                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
548                                   AFS_TRACE_LEVEL_VERBOSE,
549                                   "AFSCommonCreate (%p) Failed to locate name entry for %wZ Status %08lX\n",
550                                   Irp,
551                                   &uniFileName,
552                                   ntStatus));
553
554                     try_return( ntStatus);
555                 }
556
557                 //
558                 // Check for STATUS_REPARSE
559                 //
560
561                 if( ntStatus == STATUS_REPARSE)
562                 {
563
564                     uniSubstitutedPathName.Buffer = NULL;
565
566                     //
567                     // Update the information and return
568                     //
569
570                     Irp->IoStatus.Information = IO_REPARSE;
571
572                     try_return( ntStatus);
573                 }
574
575                 //
576                 // If we re-allocated the name, then update our substitute name
577                 //
578
579                 if( uniSubstitutedPathName.Buffer != uniRootFileName.Buffer)
580                 {
581
582                     uniSubstitutedPathName = uniRootFileName;
583                 }
584                 else
585                 {
586
587                     uniSubstitutedPathName.Buffer = NULL;
588                 }
589
590                 //
591                 // Check for a symlink access
592                 //
593
594                 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND &&
595                     pParentDirectoryCB != NULL)
596                 {
597
598                     //
599                     // pParentDirectoryCB DirOpenReferenceCount is still held
600                     //
601
602                     UNICODE_STRING uniFinalComponent;
603
604                     uniFinalComponent.Length = 0;
605                     uniFinalComponent.MaximumLength = 0;
606                     uniFinalComponent.Buffer = NULL;
607
608                     AFSRetrieveFinalComponent( &uniFileName,
609                                                &uniFinalComponent);
610
611                     ntStatus = AFSCheckSymlinkAccess( pParentDirectoryCB,
612                                                       &uniFinalComponent);
613
614                     if( !NT_SUCCESS( ntStatus) &&
615                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
616                     {
617
618                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
619                                       AFS_TRACE_LEVEL_VERBOSE,
620                                       "AFSCommonCreate (%p) Failing access to symlink %wZ Status %08lX\n",
621                                       Irp,
622                                       &uniFileName,
623                                       ntStatus));
624
625                         try_return( ntStatus);
626                     }
627                 }
628             }
629             else
630             {
631                 AFSNameArrayHdr    *pNameArrayClone = NULL;
632
633                 //
634                 // The FILE_OPEN_REPARSE_POINT flag has been specified and a ReparsePointPolicy
635                 // is in effect which conditionally applies depending on the type of the target
636                 // object.  Therefore, two lookup passes must be performed.
637                 //   1. Evaluate the path as if the FILE_OPEN_REPARSE_POINT flag had
638                 //      not been specified.
639                 //   2. If the target object type matches the policy, use it and ignore
640                 //      the FILE_OPEN_REPARSE_POINT flag.
641                 //   3. If the target object type does not match the policy, perform
642                 //      a second pass that opens the reparse point.
643                 //   4. If the target object cannot be evaluated, perform the second pass
644                 //      that opens the reparse point.
645
646
647                 ulNameProcessingFlags = AFS_LOCATE_FLAGS_SUBSTITUTE_NAME;
648
649                 uniSubstitutedPathName = uniRootFileName;
650
651                 //
652                 // Since we may need to replay the call with different options
653                 // the values that might be altered need to be cloned:
654                 //   1. uniRootFileName
655                 //   2. pNameArray
656                 //
657
658                 pNameArrayClone = AFSInitNameArray( NULL, 0);
659
660                 if ( pNameArrayClone == NULL)
661                 {
662
663                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
664                                   AFS_TRACE_LEVEL_VERBOSE,
665                                   "AFSCommonCreate (%p) Failed to initialize name array clone\n",
666                                   Irp));
667
668                     try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
669                 }
670
671                 ntStatus = AFSPopulateNameArrayFromRelatedArray( pNameArrayClone,
672                                                                  pNameArray,
673                                                                  NULL);
674
675                 if ( !NT_SUCCESS(ntStatus))
676                 {
677
678                     AFSFreeNameArray( pNameArrayClone);
679
680                     try_return( ntStatus);
681                 }
682
683                 //
684                 // Now that the data is saved perform the lookup to determine
685                 // what the target resolves to.
686                 //
687
688                 ntStatus = AFSLocateNameEntry( &stAuthGroup,
689                                                pFileObject,
690                                                &uniRootFileName,
691                                                &uniParsedFileName,
692                                                pNameArray,
693                                                ulNameProcessingFlags,
694                                                pVolumeCB,
695                                                pParentDirectoryCB,
696                                                &pNewVolumeCB,
697                                                &NewVolumeReferenceReason,
698                                                &pNewParentDirectoryCB,
699                                                &pDirectoryCB,
700                                                &uniComponentName);
701
702                 if ( ntStatus == STATUS_SUCCESS ||
703                      ntStatus == STATUS_REPARSE ||
704                      ntStatus == STATUS_OBJECT_NAME_NOT_FOUND ||
705                      ntStatus == STATUS_ACCESS_DENIED)
706                 {
707                     //
708                     // Decide what to do based upon the ReparsePointPolicy
709                     // and the type of the target object.
710                     //
711
712                     if ( ntStatus == STATUS_SUCCESS &&
713                          AFSIgnoreReparsePointToFile() &&
714                          pDirectoryCB->ObjectInformation->FileType == AFS_FILE_TYPE_FILE)
715                     {
716
717                         //
718                         // We found an entity that matches the policy.
719                         // Therefore, we are done.  Cleanup the cloned data
720                         // and clear the FILE_OPEN_REPARSE_FLAG so we do not
721                         // later mark the CCB with CCB_FLAG_MASK_OPENED_REPARSE_POINT.
722                         //
723
724                         AFSFreeNameArray( pNameArrayClone);
725
726                         pNameArrayClone = NULL;
727
728                         ClearFlag( ulOptions, FILE_OPEN_REPARSE_POINT);
729                     }
730                     else
731                     {
732                         //
733                         //  There is no matching policy, so we need to cleanup the
734                         //  output values from AFSLocateNameEntry(), restore the
735                         //  cloned information, and re-issue the request attempting
736                         //  to open the reparse point (if any).
737                         //
738
739                         if ( pNewVolumeCB != NULL)
740                         {
741
742                             lCount = AFSVolumeDecrement( pNewVolumeCB,
743                                                          NewVolumeReferenceReason);
744
745                             pNewVolumeCB = NULL;
746
747                             NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
748                         }
749
750                         if ( pNewParentDirectoryCB)
751                         {
752
753                             lCount = InterlockedDecrement( &pNewParentDirectoryCB->DirOpenReferenceCount);
754
755                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
756                                           AFS_TRACE_LEVEL_VERBOSE,
757                                           "AFSCommonCreate DecrementY count on %wZ DE %p Ccb %p Cnt %d\n",
758                                           &pNewParentDirectoryCB->NameInformation.FileName,
759                                           pNewParentDirectoryCB,
760                                           pCcb,
761                                           lCount));
762
763                             pNewParentDirectoryCB = NULL;
764                         }
765
766                         if ( pDirectoryCB)
767                         {
768
769                             lCount = InterlockedDecrement( &pDirectoryCB->DirOpenReferenceCount);
770
771                             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
772                                           AFS_TRACE_LEVEL_VERBOSE,
773                                           "AFSCommonCreate DecrementZ count on %wZ DE %p Ccb %p Cnt %d\n",
774                                           &pDirectoryCB->NameInformation.FileName,
775                                           pDirectoryCB,
776                                           pCcb,
777                                           lCount));
778
779                             pDirectoryCB = NULL;
780                         }
781
782                         RtlZeroMemory( &uniComponentName,
783                                        sizeof( UNICODE_STRING));
784
785                         if ( uniSubstitutedPathName.Buffer != uniRootFileName.Buffer)
786                         {
787
788                             AFSExFreePoolWithTag( uniRootFileName.Buffer, 0);
789
790                             uniRootFileName = uniSubstitutedPathName;
791                         }
792
793                         AFSFreeNameArray( pNameArray);
794
795                         pNameArray = pNameArrayClone;
796
797                         pNameArrayClone = NULL;
798
799                         //
800                         // Retry the lookup
801                         //
802
803                         ulNameProcessingFlags |= (AFS_LOCATE_FLAGS_NO_MP_TARGET_EVAL |
804                                                    AFS_LOCATE_FLAGS_NO_SL_TARGET_EVAL |
805                                                    AFS_LOCATE_FLAGS_NO_DFS_LINK_EVAL);
806
807                         ntStatus = AFSLocateNameEntry( &stAuthGroup,
808                                                        pFileObject,
809                                                        &uniRootFileName,
810                                                        &uniParsedFileName,
811                                                        pNameArray,
812                                                        ulNameProcessingFlags,
813                                                        pVolumeCB,
814                                                        pParentDirectoryCB,
815                                                        &pNewVolumeCB,
816                                                        &NewVolumeReferenceReason,
817                                                        &pNewParentDirectoryCB,
818                                                        &pDirectoryCB,
819                                                        &uniComponentName);
820                     }
821                 }
822                 else
823                 {
824
825                     AFSFreeNameArray( pNameArrayClone);
826
827                     pNameArrayClone = NULL;
828                 }
829
830                 if ( pNewVolumeCB != NULL)
831                 {
832
833                     //
834                     // AFSLocateNameEntry returns pNewVolumeCB with a reference held
835                     // even if pVolumeCB == pNewVolumeCB.  It is always safe to release
836                     // the reference on pVolumeCB that was held prior to the call.
837                     // If pVolumeCB == pNewVolumeCB, the reference from AFSLocateNameEntry
838                     // will be released second.
839                     //
840
841                     lCount = AFSVolumeDecrement( pVolumeCB,
842                                                  VolumeReferenceReason);
843
844                     AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
845                                   AFS_TRACE_LEVEL_VERBOSE,
846                                   "AFSCommonCreate Decrement count on volume %p Reason %u Cnt %d\n",
847                                   pVolumeCB,
848                                   VolumeReferenceReason,
849                                   lCount));
850
851                     pVolumeCB = pNewVolumeCB;
852
853                     pNewVolumeCB = NULL;
854
855                     VolumeReferenceReason = NewVolumeReferenceReason;
856
857                     NewVolumeReferenceReason = AFS_VOLUME_REFERENCE_INVALID;
858
859                     bReleaseVolume = (pVolumeCB != NULL);
860                 }
861
862                 //
863                 // AFSLocateNameEntry does not alter the reference count of
864                 // pParentDirectoryCB and it returns pNewParentDirectoryCB with
865                 // a reference held.
866                 //
867
868                 if ( bReleaseParentDir)
869                 {
870
871                     lCount = InterlockedDecrement( &pParentDirectoryCB->DirOpenReferenceCount);
872
873                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
874                                   AFS_TRACE_LEVEL_VERBOSE,
875                                   "AFSCommonCreate DecrementX count on %wZ DE %p Ccb %p Cnt %d\n",
876                                   &pParentDirectoryCB->NameInformation.FileName,
877                                   pParentDirectoryCB,
878                                   pCcb,
879                                   lCount));
880                 }
881
882                 pParentDirectoryCB = pNewParentDirectoryCB;
883
884                 pNewParentDirectoryCB = NULL;
885
886                 bReleaseParentDir = (pParentDirectoryCB != NULL);
887
888                 if ( pDirectoryCB)
889                 {
890
891                     bReleaseDir = TRUE;
892                 }
893
894                 if( !NT_SUCCESS( ntStatus) &&
895                     ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
896                 {
897
898                     if ( uniSubstitutedPathName.Buffer == uniRootFileName.Buffer)
899                     {
900                         uniSubstitutedPathName.Buffer = NULL;
901                     }
902
903                     //
904                     // AFSLocateNameEntry released the Parent while walking the
905                     // branch
906                     //
907
908                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
909                                   AFS_TRACE_LEVEL_VERBOSE,
910                                   "AFSCommonCreate (%p) Failed to locate name entry for %wZ Status %08lX\n",
911                                   Irp,
912                                   &uniFileName,
913                                   ntStatus));
914
915                     try_return( ntStatus);
916                 }
917
918                 //
919                 // Check for STATUS_REPARSE
920                 //
921
922                 if( ntStatus == STATUS_REPARSE)
923                 {
924
925                     uniSubstitutedPathName.Buffer = NULL;
926
927                     //
928                     // Update the information and return
929                     //
930
931                     Irp->IoStatus.Information = IO_REPARSE;
932
933                     try_return( ntStatus);
934                 }
935
936                 //
937                 // If we re-allocated the name, then update our substitute name
938                 //
939
940                 if( uniSubstitutedPathName.Buffer != uniRootFileName.Buffer)
941                 {
942
943                     uniSubstitutedPathName = uniRootFileName;
944                 }
945                 else
946                 {
947
948                     uniSubstitutedPathName.Buffer = NULL;
949                 }
950
951                 //
952                 // Check for a symlink access
953                 //
954
955                 if( ntStatus == STATUS_OBJECT_NAME_NOT_FOUND &&
956                     pParentDirectoryCB != NULL)
957                 {
958
959                     //
960                     // pParentDirectoryCB DirOpenReferenceCount is still held
961                     //
962
963                     UNICODE_STRING uniFinalComponent;
964
965                     uniFinalComponent.Length = 0;
966                     uniFinalComponent.MaximumLength = 0;
967                     uniFinalComponent.Buffer = NULL;
968
969                     AFSRetrieveFinalComponent( &uniFileName,
970                                                &uniFinalComponent);
971
972                     ntStatus = AFSCheckSymlinkAccess( pParentDirectoryCB,
973                                                       &uniFinalComponent);
974
975                     if( !NT_SUCCESS( ntStatus) &&
976                         ntStatus != STATUS_OBJECT_NAME_NOT_FOUND)
977                     {
978
979                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
980                                       AFS_TRACE_LEVEL_VERBOSE,
981                                       "AFSCommonCreate (%p) Failing access to symlink %wZ Status %08lX\n",
982                                       Irp,
983                                       &uniFileName,
984                                       ntStatus));
985
986                         try_return( ntStatus);
987                     }
988                 }
989             }
990         }
991
992         //
993         // If we have no parent then this is a root open, be sure there is a directory entry
994         // for the root
995         //
996
997         else if( pParentDirectoryCB == NULL &&
998                  pDirectoryCB == NULL)
999         {
1000
1001             pDirectoryCB = pVolumeCB->DirectoryCB;
1002
1003             lCount = InterlockedIncrement( &pDirectoryCB->DirOpenReferenceCount);
1004
1005             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1006                           AFS_TRACE_LEVEL_VERBOSE,
1007                           "AFSCommonCreate Increment0 count on %wZ DE %p Ccb %p Cnt %d\n",
1008                           &pDirectoryCB->NameInformation.FileName,
1009                           pDirectoryCB,
1010                           pCcb,
1011                           lCount));
1012
1013             bReleaseDir = TRUE;
1014         }
1015
1016         if( bOpenTargetDirectory)
1017         {
1018
1019             //
1020             // If we have a directory cb for the entry then dereference it and reference the parent
1021             //
1022
1023             if( pDirectoryCB != NULL)
1024             {
1025
1026                 if ( !bReleaseParentDir)
1027                 {
1028
1029                     //
1030                     // Perform in this order to prevent thrashing
1031                     //
1032
1033                     lCount = InterlockedIncrement( &pParentDirectoryCB->DirOpenReferenceCount);
1034
1035                     AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1036                                   AFS_TRACE_LEVEL_VERBOSE,
1037                                   "AFSCommonCreate Increment1 count on %wZ DE %p Ccb %p Cnt %d\n",
1038                                   &pParentDirectoryCB->NameInformation.FileName,
1039                                   pParentDirectoryCB,
1040                                   pCcb,
1041                                   lCount));
1042
1043                     bReleaseParentDir = TRUE;
1044                 }
1045
1046                 //
1047                 // Do NOT decrement the reference count on the pDirectoryCB yet.
1048                 // The BackupEntry below might drop the count to zero leaving
1049                 // the entry subject to being deleted and we need some of the
1050                 // contents during later processing
1051                 //
1052
1053                 AFSBackupEntry( pNameArray);
1054             }
1055
1056             //
1057             // OK, open the target directory
1058             //
1059
1060             if( uniComponentName.Length == 0)
1061             {
1062                 AFSRetrieveFinalComponent( &uniFileName,
1063                                            &uniComponentName);
1064             }
1065
1066             ntStatus = AFSOpenTargetDirectory( Irp,
1067                                                pVolumeCB,
1068                                                pParentDirectoryCB,
1069                                                pDirectoryCB,
1070                                                &uniComponentName,
1071                                                &pFcb,
1072                                                &pCcb);
1073
1074             if( !NT_SUCCESS( ntStatus))
1075             {
1076
1077                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1078                               AFS_TRACE_LEVEL_ERROR,
1079                               "AFSCommonCreate Failed to open target directory %wZ Status %08lX\n",
1080                               &pParentDirectoryCB->NameInformation.FileName,
1081                               ntStatus));
1082             }
1083
1084             try_return( ntStatus);
1085         }
1086
1087         if ( BooleanFlagOn( ulOptions, FILE_OPEN_REPARSE_POINT))
1088         {
1089
1090             if( pDirectoryCB == NULL ||
1091                 !BooleanFlagOn( pDirectoryCB->ObjectInformation->FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT))
1092             {
1093                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1094                               AFS_TRACE_LEVEL_VERBOSE,
1095                               "AFSCommonCreate (%p) Reparse open request but attribute not set for %wZ DirCB %p Type %08lX\n",
1096                               Irp,
1097                               &uniFileName,
1098                               pDirectoryCB,
1099                               pDirectoryCB ? pDirectoryCB->ObjectInformation->FileType : 0));
1100             }
1101             else
1102             {
1103                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1104                               AFS_TRACE_LEVEL_VERBOSE,
1105                               "AFSCommonCreate (%p) Opening as reparse point %wZ Type %08lX\n",
1106                               Irp,
1107                               &uniFileName,
1108                               pDirectoryCB->ObjectInformation->FileType));
1109
1110                 bOpenedReparsePoint = TRUE;
1111             }
1112         }
1113
1114         //
1115         // Based on the options passed in, process the file accordingly.
1116         //
1117
1118         if( ulCreateDisposition == FILE_CREATE ||
1119             ( ( ulCreateDisposition == FILE_OPEN_IF ||
1120                 ulCreateDisposition == FILE_OVERWRITE_IF) &&
1121               pDirectoryCB == NULL))
1122         {
1123
1124             if( uniComponentName.Length == 0 ||
1125                 pDirectoryCB != NULL)
1126             {
1127
1128                 //
1129                 // We traversed the entire path so we found each entry,
1130                 // fail with collision
1131                 //
1132
1133                 if( pDirectoryCB != NULL)
1134                 {
1135
1136                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1137                                   AFS_TRACE_LEVEL_VERBOSE,
1138                                   "AFSCommonCreate Object name collision on create of %wZ Status %08lX\n",
1139                                   &pDirectoryCB->NameInformation.FileName,
1140                                   ntStatus));
1141                 }
1142                 else
1143                 {
1144
1145                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1146                                   AFS_TRACE_LEVEL_VERBOSE,
1147                                   "AFSCommonCreate Object name collision on create Status %08lX\n",
1148                                   ntStatus));
1149                 }
1150
1151                 try_return( ntStatus = STATUS_OBJECT_NAME_COLLISION);
1152             }
1153
1154             //
1155             // OK, go and create the node
1156             //
1157
1158             ntStatus = AFSProcessCreate( Irp,
1159                                          &stAuthGroup,
1160                                          pVolumeCB,
1161                                          pParentDirectoryCB,
1162                                          &uniFileName,
1163                                          &uniComponentName,
1164                                          &uniRootFileName,
1165                                          &pFcb,
1166                                          &pCcb);
1167
1168             if( !NT_SUCCESS( ntStatus))
1169             {
1170
1171                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1172                               AFS_TRACE_LEVEL_ERROR,
1173                               "AFSCommonCreate Failed to create of %wZ in directory %wZ Status %08lX\n",
1174                               &uniComponentName,
1175                               &pParentDirectoryCB->NameInformation.FileName,
1176                               ntStatus));
1177             }
1178
1179             try_return( ntStatus);
1180         }
1181
1182         //
1183         // We should not have an extra component except for PIOCtl opens
1184         //
1185
1186         if( uniComponentName.Length > 0)
1187         {
1188
1189             //
1190             // If this is an open on "_._AFS_IOCTL_._" then perform handling on it accordingly
1191             //
1192
1193             if( RtlCompareUnicodeString( &AFSPIOCtlName,
1194                                          &uniComponentName,
1195                                          TRUE) == 0)
1196             {
1197
1198                 //
1199                 // AFSOpenIOCtlFcb does not free a DirOpenReferenceCount for
1200                 // pParentDirectoryCB.
1201                 //
1202
1203                 ntStatus = AFSOpenIOCtlFcb( Irp,
1204                                             &stAuthGroup,
1205                                             pParentDirectoryCB,
1206                                             &pFcb,
1207                                             &pCcb);
1208
1209                 if( !NT_SUCCESS( ntStatus))
1210                 {
1211
1212                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1213                                   AFS_TRACE_LEVEL_ERROR,
1214                                   "AFSCommonCreate Failed to IOCtl open on %wZ Status %08lX\n",
1215                                   &uniComponentName,
1216                                   ntStatus));
1217                 }
1218             }
1219             else
1220             {
1221
1222                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1223                               AFS_TRACE_LEVEL_VERBOSE,
1224                               "AFSCommonCreate (%p) File %wZ name not found\n",
1225                               Irp,
1226                               &uniFileName));
1227
1228                 ntStatus = STATUS_OBJECT_NAME_NOT_FOUND;
1229             }
1230
1231             try_return( ntStatus);
1232         }
1233
1234         //
1235         // For root opens the parent will be NULL
1236         //
1237
1238         if( pParentDirectoryCB == NULL)
1239         {
1240
1241             //
1242             // Check for the delete on close flag for the root
1243             //
1244
1245             if( BooleanFlagOn( ulOptions, FILE_DELETE_ON_CLOSE ))
1246             {
1247
1248                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1249                               AFS_TRACE_LEVEL_ERROR,
1250                               "AFSCommonCreate (%p) Attempt to open root as delete on close\n",
1251                               Irp));
1252
1253                 try_return( ntStatus = STATUS_CANNOT_DELETE);
1254             }
1255
1256             //
1257             // If this is the target directory, then bail
1258             //
1259
1260             if( bOpenTargetDirectory)
1261             {
1262
1263                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1264                               AFS_TRACE_LEVEL_ERROR,
1265                               "AFSCommonCreate (%p) Attempt to open root as target directory\n",
1266                               Irp));
1267
1268                 try_return( ntStatus = STATUS_INVALID_PARAMETER);
1269             }
1270
1271             //
1272             // Go and open the root of the volume
1273             //
1274
1275             ntStatus = AFSOpenRoot( Irp,
1276                                     pVolumeCB,
1277                                     &stAuthGroup,
1278                                     &pFcb,
1279                                     &pCcb);
1280
1281             if( !NT_SUCCESS( ntStatus))
1282             {
1283
1284                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1285                               AFS_TRACE_LEVEL_ERROR,
1286                               "AFSCommonCreate Failed to open volume root %08lX-%08lX Status %08lX\n",
1287                               pVolumeCB->ObjectInformation.FileId.Cell,
1288                               pVolumeCB->ObjectInformation.FileId.Volume,
1289                               ntStatus));
1290             }
1291
1292             try_return( ntStatus);
1293         }
1294
1295         //
1296         // At this point if we have no pDirectoryCB it was not found.
1297         //
1298
1299         if( pDirectoryCB == NULL)
1300         {
1301
1302             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1303                           AFS_TRACE_LEVEL_ERROR,
1304                           "AFSCommonCreate Failing access to %wZ Name not found\n",
1305                           &uniFileName));
1306
1307             try_return( ntStatus = STATUS_OBJECT_NAME_NOT_FOUND);
1308         }
1309
1310         if( ulCreateDisposition == FILE_OVERWRITE ||
1311             ulCreateDisposition == FILE_SUPERSEDE ||
1312             ulCreateDisposition == FILE_OVERWRITE_IF)
1313         {
1314
1315             //
1316             // Go process a file for overwrite or supersede.
1317             //
1318
1319             ntStatus = AFSProcessOverwriteSupersede( DeviceObject,
1320                                                      Irp,
1321                                                      pVolumeCB,
1322                                                      &stAuthGroup,
1323                                                      pParentDirectoryCB,
1324                                                      pDirectoryCB,
1325                                                      &pFcb,
1326                                                      &pCcb);
1327
1328             if( !NT_SUCCESS( ntStatus))
1329             {
1330
1331                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1332                               AFS_TRACE_LEVEL_ERROR,
1333                               "AFSCommonCreate Failed overwrite/supersede on %wZ Status %08lX\n",
1334                               &pDirectoryCB->NameInformation.FileName,
1335                               ntStatus));
1336             }
1337
1338             try_return( ntStatus);
1339         }
1340
1341         //
1342         // Trying to open the file
1343         //
1344
1345         ntStatus = AFSProcessOpen( Irp,
1346                                    &stAuthGroup,
1347                                    pVolumeCB,
1348                                    pParentDirectoryCB,
1349                                    pDirectoryCB,
1350                                    bOpenedReparsePoint,
1351                                    &pFcb,
1352                                    &pCcb);
1353
1354         if( !NT_SUCCESS( ntStatus))
1355         {
1356
1357             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1358                           AFS_TRACE_LEVEL_ERROR,
1359                           "AFSCommonCreate Failed open on %wZ Status %08lX\n",
1360                           &pDirectoryCB->NameInformation.FileName,
1361                           ntStatus));
1362         }
1363
1364 try_exit:
1365
1366         if( NT_SUCCESS( ntStatus) &&
1367             ntStatus != STATUS_REPARSE)
1368         {
1369
1370             if( pCcb != NULL)
1371             {
1372
1373                 AFSAcquireExcl( &pCcb->NPCcb->CcbLock,
1374                                 TRUE);
1375
1376                 RtlCopyMemory( &pCcb->AuthGroup,
1377                                &stAuthGroup,
1378                                sizeof( GUID));
1379
1380                 //
1381                 // If we have a substitute name, then use it
1382                 //
1383
1384                 if( uniSubstitutedPathName.Buffer != NULL)
1385                 {
1386
1387                     pCcb->FullFileName = uniSubstitutedPathName;
1388
1389                     SetFlag( pCcb->Flags, CCB_FLAG_FREE_FULL_PATHNAME);
1390
1391                     ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
1392                 }
1393                 else
1394                 {
1395
1396                     pCcb->FullFileName = uniRootFileName;
1397
1398                     if( BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER))
1399                     {
1400
1401                         SetFlag( pCcb->Flags, CCB_FLAG_FREE_FULL_PATHNAME);
1402
1403                         ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
1404                     }
1405                 }
1406
1407                 if( bOpenedReparsePoint)
1408                 {
1409                     SetFlag( pCcb->Flags, CCB_FLAG_MASK_OPENED_REPARSE_POINT);
1410                 }
1411
1412                 lCount = pCcb->DirectoryCB->DirOpenReferenceCount;
1413
1414                 AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1415                               AFS_TRACE_LEVEL_VERBOSE,
1416                               "AFSCommonCreate Count on %wZ DE %p Ccb %p Cnt %d\n",
1417                               &pCcb->DirectoryCB->NameInformation.FileName,
1418                               pCcb->DirectoryCB,
1419                               pCcb,
1420                               lCount));
1421
1422                 ASSERT( lCount >= 0);
1423
1424                 pCcb->CurrentDirIndex = 0;
1425
1426                 if( !BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_ROOT_ACCESS))
1427                 {
1428
1429                     SetFlag( pCcb->Flags, CCB_FLAG_RETURN_RELATIVE_ENTRIES);
1430                 }
1431
1432                 //
1433                 // Save off the name array for this instance
1434                 //
1435
1436                 pCcb->NameArray = pNameArray;
1437
1438                 pNameArray = NULL;
1439
1440                 AFSReleaseResource( &pCcb->NPCcb->CcbLock);
1441             }
1442
1443             //
1444             // If we make it here then init the FO for the request.
1445             //
1446
1447             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1448                           AFS_TRACE_LEVEL_VERBOSE_2,
1449                           "AFSCommonCreate (%p) FileObject %p FsContext %p FsContext2 %p\n",
1450                           Irp,
1451                           pFileObject,
1452                           pFcb,
1453                           pCcb));
1454
1455             pFileObject->FsContext = (void *)pFcb;
1456
1457             pFileObject->FsContext2 = (void *)pCcb;
1458
1459             if( pFcb != NULL)
1460             {
1461
1462                 ASSERT( pFcb->OpenHandleCount > 0);
1463
1464                 ClearFlag( pFcb->Flags, AFS_FCB_FILE_CLOSED);
1465
1466                 //
1467                 // For files perform additional processing
1468                 //
1469
1470                 switch( pFcb->Header.NodeTypeCode)
1471                 {
1472
1473                     case AFS_FILE_FCB:
1474                     case AFS_IOCTL_FCB:
1475                     {
1476
1477                         pFileObject->SectionObjectPointer = &pFcb->NPFcb->SectionObjectPointers;
1478                     }
1479                 }
1480
1481                 //
1482                 // If the user did not request nobuffering then mark the FO as cacheable
1483                 //
1484
1485                 if( bNoIntermediateBuffering)
1486                 {
1487
1488                     pFileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
1489                 }
1490                 else
1491                 {
1492
1493                     pFileObject->Flags |= FO_CACHE_SUPPORTED;
1494                 }
1495
1496                 //
1497                 // If the file was opened for execution then we need to set the bit in the FO
1498                 //
1499
1500                 if( BooleanFlagOn( *pDesiredAccess,
1501                                    FILE_EXECUTE))
1502                 {
1503
1504                     SetFlag( pFileObject->Flags, FO_FILE_FAST_IO_READ);
1505                 }
1506
1507                 //
1508                 // Update the last access time
1509                 //
1510
1511                 KeQuerySystemTime( &pFcb->ObjectInformation->LastAccessTime);
1512
1513                 if( pCcb != NULL)
1514                 {
1515                     AFSInsertCcb( pFcb,
1516                                   pCcb);
1517                 }
1518             }
1519             else
1520             {
1521
1522                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1523                               AFS_TRACE_LEVEL_ERROR,
1524                               "AFSCommonCreate (%p) Returning with NULL Fcb FileObject %p FsContext %p FsContext2 %p\n",
1525                               Irp,
1526                               pFileObject,
1527                               pFcb,
1528                               pCcb));
1529             }
1530         }
1531         else
1532         {
1533             if( NT_SUCCESS( ntStatus) &&
1534                 ntStatus == STATUS_REPARSE)
1535             {
1536
1537                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1538                               AFS_TRACE_LEVEL_ERROR,
1539                               "AFSCommonCreate (%p) STATUS_REPARSE FileObject %p FsContext %p FsContext2 %p\n",
1540                               Irp,
1541                               pFileObject,
1542                               pFcb,
1543                               pCcb));
1544             }
1545
1546             //
1547             // Free up the sub name if we have one
1548             //
1549
1550             if( uniSubstitutedPathName.Buffer != NULL)
1551             {
1552
1553                 AFSExFreePoolWithTag( uniSubstitutedPathName.Buffer, 0);
1554
1555                 ClearFlag( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER);
1556             }
1557         }
1558
1559         //
1560         // Free up the name array ...
1561         //
1562
1563         if( pNameArray != NULL)
1564         {
1565
1566             AFSFreeNameArray( pNameArray);
1567         }
1568
1569         if( BooleanFlagOn( ulParseFlags, AFS_PARSE_FLAG_FREE_FILE_BUFFER))
1570         {
1571
1572             AFSExFreePoolWithTag( uniRootFileName.Buffer, 0);
1573         }
1574
1575         if( bReleaseVolume)
1576         {
1577
1578             lCount = AFSVolumeDecrement( pVolumeCB,
1579                                          VolumeReferenceReason);
1580
1581             AFSDbgTrace(( AFS_SUBSYSTEM_VOLUME_REF_COUNTING,
1582                           AFS_TRACE_LEVEL_VERBOSE,
1583                           "AFSCommonCreate Decrement count on Volume %08lX Reason %u Cnt %d\n",
1584                           pVolumeCB,
1585                           VolumeReferenceReason,
1586                           lCount));
1587         }
1588
1589         if ( bReleaseDir)
1590         {
1591
1592             //
1593             // Release the reference from AFSLocateNameEntry
1594             //
1595
1596             lCount = InterlockedDecrement( &pDirectoryCB->DirOpenReferenceCount);
1597
1598             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1599                           AFS_TRACE_LEVEL_VERBOSE,
1600                           "AFSCommonCreate Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1601                           &pDirectoryCB->NameInformation.FileName,
1602                           pDirectoryCB,
1603                           pCcb,
1604                           lCount));
1605
1606             ASSERT( lCount >= 0);
1607         }
1608
1609         if ( bReleaseParentDir)
1610         {
1611
1612             //
1613             // Release the reference from AFSLocateNameEntry
1614             //
1615
1616             lCount = InterlockedDecrement( &pParentDirectoryCB->DirOpenReferenceCount);
1617
1618             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
1619                           AFS_TRACE_LEVEL_VERBOSE,
1620                           "AFSCommonCreate Decrement count on %wZ DE %p Ccb %p Cnt %d\n",
1621                           &pParentDirectoryCB->NameInformation.FileName,
1622                           pParentDirectoryCB,
1623                           pCcb,
1624                           lCount));
1625
1626             ASSERT( lCount >= 0);
1627         }
1628
1629         //
1630         // Setup the Irp for completion, the Information has been set previously
1631         //
1632
1633         Irp->IoStatus.Status = ntStatus;
1634     }
1635
1636     return ntStatus;
1637 }
1638
1639 NTSTATUS
1640 AFSOpenAFSRoot( IN PIRP Irp,
1641                 IN AFSFcb **Fcb,
1642                 IN AFSCcb **Ccb)
1643 {
1644
1645     NTSTATUS ntStatus = STATUS_SUCCESS;
1646     LONG lCount;
1647
1648     __Enter
1649     {
1650
1651         //
1652         // Initialize the Ccb for the file.
1653         //
1654
1655         ntStatus = AFSInitCcb( Ccb,
1656                                AFSGlobalRoot->DirectoryCB,
1657                                0,
1658                                0);
1659
1660         if( !NT_SUCCESS( ntStatus))
1661         {
1662
1663             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1664                           AFS_TRACE_LEVEL_ERROR,
1665                           "AFSOpenAFSRoot (%p) Failed to allocate Ccb\n",
1666                           Irp));
1667
1668             try_return( ntStatus);
1669         }
1670
1671         //
1672         // Increment the open count on this Fcb
1673         //
1674
1675         lCount = InterlockedIncrement( &AFSGlobalRoot->RootFcb->OpenReferenceCount);
1676
1677         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1678                       AFS_TRACE_LEVEL_VERBOSE,
1679                       "AFSOpenAFSRoot Increment count on Fcb %p Cnt %d\n",
1680                       AFSGlobalRoot->RootFcb,
1681                       lCount));
1682
1683         lCount = InterlockedIncrement( &AFSGlobalRoot->RootFcb->OpenHandleCount);
1684
1685         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1686                       AFS_TRACE_LEVEL_VERBOSE,
1687                       "AFSOpenAFSRoot Increment handle count on Fcb %p Cnt %d\n",
1688                       AFSGlobalRoot->RootFcb,
1689                       lCount));
1690
1691         *Fcb = AFSGlobalRoot->RootFcb;
1692
1693         //
1694         // Return the open result for this file
1695         //
1696
1697         Irp->IoStatus.Information = FILE_OPENED;
1698
1699 try_exit:
1700
1701         NOTHING;
1702     }
1703
1704     return ntStatus;
1705 }
1706
1707 NTSTATUS
1708 AFSOpenRoot( IN PIRP Irp,
1709              IN AFSVolumeCB *VolumeCB,
1710              IN GUID *AuthGroup,
1711              OUT AFSFcb **RootFcb,
1712              OUT AFSCcb **Ccb)
1713 {
1714
1715     NTSTATUS ntStatus = STATUS_SUCCESS;
1716     PFILE_OBJECT pFileObject = NULL;
1717     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
1718     PACCESS_MASK pDesiredAccess = NULL;
1719     USHORT usShareAccess;
1720     ULONG ulOptions;
1721     BOOLEAN bAllocatedCcb = FALSE;
1722     BOOLEAN bReleaseFcb = FALSE;
1723     AFSFileOpenCB   stOpenCB;
1724     AFSFileOpenResultCB stOpenResultCB;
1725     ULONG       ulResultLen = 0;
1726     LONG        lCount;
1727
1728     __Enter
1729     {
1730
1731         pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
1732         usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
1733         ulOptions = pIrpSp->Parameters.Create.Options;
1734
1735         pFileObject = pIrpSp->FileObject;
1736
1737         if( BooleanFlagOn( ulOptions, FILE_NON_DIRECTORY_FILE))
1738         {
1739
1740             ntStatus = STATUS_FILE_IS_A_DIRECTORY;
1741
1742             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1743                           AFS_TRACE_LEVEL_ERROR,
1744                           "AFSOpenRoot (%p) Attempt to open root as file Status %08lX\n",
1745                           Irp,
1746                           ntStatus));
1747
1748             try_return( ntStatus);
1749         }
1750
1751         //
1752         // Check if we should go and retrieve updated information for the node
1753         //
1754
1755         ntStatus = AFSValidateEntry( VolumeCB->DirectoryCB,
1756                                      AuthGroup,
1757                                      FALSE,
1758                                      TRUE);
1759
1760         if( !NT_SUCCESS( ntStatus))
1761         {
1762
1763             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1764                           AFS_TRACE_LEVEL_ERROR,
1765                           "AFSOpenRoot (%p) Failed to validate root entry Status %08lX\n",
1766                           Irp,
1767                           ntStatus));
1768
1769             try_return( ntStatus);
1770         }
1771
1772         //
1773         // Check with the service that we can open the file
1774         //
1775
1776         RtlZeroMemory( &stOpenCB,
1777                        sizeof( AFSFileOpenCB));
1778
1779         stOpenCB.DesiredAccess = *pDesiredAccess;
1780
1781         stOpenCB.ShareAccess = usShareAccess;
1782
1783         stOpenResultCB.GrantedAccess = 0;
1784
1785         ulResultLen = sizeof( AFSFileOpenResultCB);
1786
1787         ntStatus = AFSProcessRequest( AFS_REQUEST_TYPE_OPEN_FILE,
1788                                       AFS_REQUEST_FLAG_SYNCHRONOUS | AFS_REQUEST_FLAG_HOLD_FID,
1789                                       AuthGroup,
1790                                       NULL,
1791                                       &VolumeCB->ObjectInformation.FileId,
1792                                       VolumeCB->VolumeInformation.Cell,
1793                                       VolumeCB->VolumeInformation.CellLength,
1794                                       (void *)&stOpenCB,
1795                                       sizeof( AFSFileOpenCB),
1796                                       (void *)&stOpenResultCB,
1797                                       &ulResultLen);
1798
1799         if( !NT_SUCCESS( ntStatus))
1800         {
1801
1802             UNICODE_STRING uniGUID;
1803
1804             uniGUID.Length = 0;
1805             uniGUID.MaximumLength = 0;
1806             uniGUID.Buffer = NULL;
1807
1808             if( AuthGroup != NULL)
1809             {
1810                 RtlStringFromGUID( *AuthGroup,
1811                                    &uniGUID);
1812             }
1813
1814             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1815                           AFS_TRACE_LEVEL_ERROR,
1816                           "AFSOpenRoot (%p) Failed open in service volume %08lX-%08lX AuthGroup %wZ Status %08lX\n",
1817                           Irp,
1818                           VolumeCB->ObjectInformation.FileId.Cell,
1819                           VolumeCB->ObjectInformation.FileId.Volume,
1820                           &uniGUID,
1821                           ntStatus));
1822
1823             if( AuthGroup != NULL)
1824             {
1825                 RtlFreeUnicodeString( &uniGUID);
1826             }
1827
1828             try_return( ntStatus);
1829         }
1830
1831         //
1832         // If the entry is not initialized then do it now
1833         //
1834
1835         if( !BooleanFlagOn( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED))
1836         {
1837
1838             AFSAcquireExcl( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock,
1839                             TRUE);
1840
1841             ntStatus = AFSEnumerateDirectory( AuthGroup,
1842                                               &VolumeCB->ObjectInformation,
1843                                               TRUE);
1844
1845             if( !NT_SUCCESS( ntStatus))
1846             {
1847
1848                 AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1849
1850                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1851                               AFS_TRACE_LEVEL_ERROR,
1852                               "AFSOpenRoot (%p) Failed to enumerate directory Status %08lX\n",
1853                               Irp,
1854                               ntStatus));
1855
1856                 try_return( ntStatus);
1857             }
1858
1859             AFSReleaseResource( VolumeCB->ObjectInformation.Specific.Directory.DirectoryNodeHdr.TreeLock);
1860         }
1861
1862         //
1863         // If the root fcb has been initialized then check access otherwise
1864         // init the volume fcb
1865         //
1866
1867         ntStatus = AFSInitRootFcb( (ULONGLONG)PsGetCurrentProcessId(),
1868                                    VolumeCB);
1869
1870         if( !NT_SUCCESS( ntStatus))
1871         {
1872
1873             try_return( ntStatus);
1874         }
1875
1876         lCount = InterlockedIncrement( &VolumeCB->RootFcb->OpenReferenceCount);
1877
1878         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1879                       AFS_TRACE_LEVEL_VERBOSE,
1880                       "AFSOpenRoot Increment count on Fcb %p Cnt %d\n",
1881                       VolumeCB->RootFcb,
1882                       lCount));
1883
1884         bReleaseFcb = TRUE;
1885
1886         //
1887         // If there are current opens on the Fcb, check the access.
1888         //
1889
1890         if( VolumeCB->RootFcb->OpenHandleCount > 0)
1891         {
1892
1893             ntStatus = IoCheckShareAccess( *pDesiredAccess,
1894                                            usShareAccess,
1895                                            pFileObject,
1896                                            &VolumeCB->RootFcb->ShareAccess,
1897                                            FALSE);
1898
1899             if( !NT_SUCCESS( ntStatus))
1900             {
1901
1902                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1903                               AFS_TRACE_LEVEL_ERROR,
1904                               "AFSOpenRoot (%p) Access check failure Status %08lX\n",
1905                               Irp,
1906                               ntStatus));
1907
1908                 try_return( ntStatus);
1909             }
1910         }
1911
1912         //
1913         // Initialize the Ccb for the file.
1914         //
1915
1916         ntStatus = AFSInitCcb( Ccb,
1917                                VolumeCB->DirectoryCB,
1918                                *pDesiredAccess,
1919                                0);
1920
1921         if( !NT_SUCCESS( ntStatus))
1922         {
1923
1924             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
1925                           AFS_TRACE_LEVEL_ERROR,
1926                           "AFSOpenRoot (%p) Failed to allocate Ccb Status %08lX\n",
1927                           Irp,
1928                           ntStatus));
1929
1930             try_return( ntStatus);
1931         }
1932
1933         bAllocatedCcb = TRUE;
1934
1935         //
1936         // OK, update the share access on the fileobject
1937         //
1938
1939         if( VolumeCB->RootFcb->OpenHandleCount > 0)
1940         {
1941
1942             IoUpdateShareAccess( pFileObject,
1943                                  &VolumeCB->RootFcb->ShareAccess);
1944         }
1945         else
1946         {
1947
1948             //
1949             // Set the access
1950             //
1951
1952             IoSetShareAccess( *pDesiredAccess,
1953                               usShareAccess,
1954                               pFileObject,
1955                               &VolumeCB->RootFcb->ShareAccess);
1956         }
1957
1958         //
1959         // Increment the open count on this Fcb
1960         //
1961
1962         lCount = InterlockedIncrement( &VolumeCB->RootFcb->OpenHandleCount);
1963
1964         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1965                       AFS_TRACE_LEVEL_VERBOSE,
1966                       "AFSOpenRoot Increment handle count on Fcb %p Cnt %d\n",
1967                       VolumeCB->RootFcb,
1968                       lCount));
1969
1970         //
1971         // Indicate the object is held
1972         //
1973
1974         SetFlag( VolumeCB->ObjectInformation.Flags, AFS_OBJECT_HELD_IN_SERVICE);
1975
1976         //
1977         // Return the open result for this file
1978         //
1979
1980         Irp->IoStatus.Information = FILE_OPENED;
1981
1982         *RootFcb = VolumeCB->RootFcb;
1983
1984 try_exit:
1985
1986         if( bReleaseFcb)
1987         {
1988             if ( !NT_SUCCESS( ntStatus))
1989             {
1990
1991                 lCount = InterlockedDecrement( &VolumeCB->RootFcb->OpenReferenceCount);
1992
1993                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
1994                               AFS_TRACE_LEVEL_VERBOSE,
1995                               "AFSOpenRoot Decrement count on Fcb %p Cnt %d\n",
1996                               VolumeCB->RootFcb,
1997                               lCount));
1998             }
1999
2000             AFSReleaseResource( VolumeCB->RootFcb->Header.Resource);
2001         }
2002
2003         if( !NT_SUCCESS( ntStatus))
2004         {
2005
2006             if( bAllocatedCcb)
2007             {
2008
2009                 AFSRemoveCcb( NULL,
2010                               *Ccb);
2011
2012                 *Ccb = NULL;
2013             }
2014
2015             Irp->IoStatus.Information = 0;
2016         }
2017     }
2018
2019     return ntStatus;
2020 }
2021
2022 NTSTATUS
2023 AFSProcessCreate( IN PIRP               Irp,
2024                   IN GUID              *AuthGroup,
2025                   IN AFSVolumeCB       *VolumeCB,
2026                   IN AFSDirectoryCB    *ParentDirCB,
2027                   IN PUNICODE_STRING    FileName,
2028                   IN PUNICODE_STRING    ComponentName,
2029                   IN PUNICODE_STRING    FullFileName,
2030                   OUT AFSFcb          **Fcb,
2031                   OUT AFSCcb          **Ccb)
2032 {
2033
2034     NTSTATUS ntStatus = STATUS_SUCCESS;
2035     PFILE_OBJECT pFileObject = NULL;
2036     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2037     ULONG ulOptions = 0;
2038     ULONG ulAttributes = 0;
2039     BOOLEAN bFileCreated = FALSE, bReleaseFcb = FALSE, bAllocatedCcb = FALSE;
2040     PACCESS_MASK pDesiredAccess = NULL;
2041     USHORT usShareAccess;
2042     AFSDirectoryCB *pDirEntry = NULL;
2043     AFSObjectInfoCB *pParentObjectInfo = NULL;
2044     AFSObjectInfoCB *pObjectInfo = NULL;
2045     LONG lCount;
2046
2047     __Enter
2048     {
2049
2050         pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
2051         usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
2052
2053         pFileObject = pIrpSp->FileObject;
2054
2055         //
2056         // Extract out the options
2057         //
2058
2059         ulOptions = pIrpSp->Parameters.Create.Options;
2060
2061         //
2062         // We pass all attributes they want to apply to the file to the create
2063         //
2064
2065         ulAttributes = pIrpSp->Parameters.Create.FileAttributes;
2066
2067         //
2068         // If this is a directory create then set the attribute correctly
2069         //
2070
2071         if( ulOptions & FILE_DIRECTORY_FILE)
2072         {
2073
2074             ulAttributes |= FILE_ATTRIBUTE_DIRECTORY;
2075         }
2076
2077         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2078                       AFS_TRACE_LEVEL_VERBOSE,
2079                       "AFSProcessCreate (%p) Creating file %wZ Attributes %08lX\n",
2080                       Irp,
2081                       FullFileName,
2082                       ulAttributes));
2083
2084         if( BooleanFlagOn( VolumeCB->VolumeInformation.FileSystemAttributes, FILE_READ_ONLY_VOLUME))
2085         {
2086
2087             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2088                           AFS_TRACE_LEVEL_ERROR,
2089                           "AFSProcessCreate Request failed due to read only volume %wZ\n",
2090                           FullFileName));
2091
2092             try_return( ntStatus = STATUS_MEDIA_WRITE_PROTECTED);
2093         }
2094
2095         pParentObjectInfo = ParentDirCB->ObjectInformation;
2096
2097         //
2098         // Allocate and insert the direntry into the parent node
2099         //
2100
2101         ntStatus = AFSCreateDirEntry( AuthGroup,
2102                                       pParentObjectInfo,
2103                                       ParentDirCB,
2104                                       FileName,
2105                                       ComponentName,
2106                                       ulAttributes,
2107                                       &pDirEntry);
2108
2109         if( !NT_SUCCESS( ntStatus))
2110         {
2111
2112             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2113                           AFS_TRACE_LEVEL_ERROR,
2114                           "AFSProcessCreate (%p) Failed to create directory entry %wZ Status %08lX\n",
2115                           Irp,
2116                           FullFileName,
2117                           ntStatus));
2118
2119             try_return( ntStatus);
2120         }
2121
2122         bFileCreated = TRUE;
2123
2124         pObjectInfo = pDirEntry->ObjectInformation;
2125
2126         if( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED) ||
2127             pObjectInfo->FileType == AFS_FILE_TYPE_UNKNOWN)
2128         {
2129
2130             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2131                           AFS_TRACE_LEVEL_VERBOSE,
2132                           "AFSProcessCreate (%p) Evaluating object %wZ FID %08lX-%08lX-%08lX-%08lX\n",
2133                           Irp,
2134                           &pDirEntry->NameInformation.FileName,
2135                           pObjectInfo->FileId.Cell,
2136                           pObjectInfo->FileId.Volume,
2137                           pObjectInfo->FileId.Vnode,
2138                           pObjectInfo->FileId.Unique));
2139
2140             ntStatus = AFSEvaluateNode( AuthGroup,
2141                                         pDirEntry);
2142
2143             if( !NT_SUCCESS( ntStatus))
2144             {
2145
2146                 if ( ntStatus == STATUS_NOT_A_DIRECTORY)
2147                 {
2148
2149                     if ( !BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2150                     {
2151
2152                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2153                                       AFS_TRACE_LEVEL_ERROR,
2154                                       "AFSProcessCreate (%p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX != NULL Status %08lX\n",
2155                                       Irp,
2156                                       &pDirEntry->NameInformation.FileName,
2157                                       pObjectInfo->FileId.Cell,
2158                                       pObjectInfo->FileId.Volume,
2159                                       pObjectInfo->FileId.Vnode,
2160                                       pObjectInfo->FileId.Unique,
2161                                       pParentObjectInfo->FileId.Cell,
2162                                       pParentObjectInfo->FileId.Volume,
2163                                       pParentObjectInfo->FileId.Vnode,
2164                                       pParentObjectInfo->FileId.Unique,
2165                                       ntStatus));
2166                     }
2167                     else if ( AFSIsEqualFID( &pParentObjectInfo->FileId, &pObjectInfo->ParentFileId))
2168                     {
2169
2170                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2171                                       AFS_TRACE_LEVEL_ERROR,
2172                                       "AFSProcessCreate (%p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2173                                       Irp,
2174                                       &pDirEntry->NameInformation.FileName,
2175                                       pObjectInfo->FileId.Cell,
2176                                       pObjectInfo->FileId.Volume,
2177                                       pObjectInfo->FileId.Vnode,
2178                                       pObjectInfo->FileId.Unique,
2179                                       pParentObjectInfo->FileId.Cell,
2180                                       pParentObjectInfo->FileId.Volume,
2181                                       pParentObjectInfo->FileId.Vnode,
2182                                       pParentObjectInfo->FileId.Unique,
2183                                       ntStatus));
2184                     }
2185                     else
2186                     {
2187
2188                         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2189                                       AFS_TRACE_LEVEL_ERROR,
2190                                       "AFSProcessCreate (%p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX PARENT %08lX-%08lX-%08lX-%08lX != %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2191                                       Irp,
2192                                       &pDirEntry->NameInformation.FileName,
2193                                       pObjectInfo->FileId.Cell,
2194                                       pObjectInfo->FileId.Volume,
2195                                       pObjectInfo->FileId.Vnode,
2196                                       pObjectInfo->FileId.Unique,
2197                                       pParentObjectInfo->FileId.Cell,
2198                                       pParentObjectInfo->FileId.Volume,
2199                                       pParentObjectInfo->FileId.Vnode,
2200                                       pParentObjectInfo->FileId.Unique,
2201                                       pObjectInfo->ParentFileId.Cell,
2202                                       pObjectInfo->ParentFileId.Volume,
2203                                       pObjectInfo->ParentFileId.Vnode,
2204                                       pObjectInfo->ParentFileId.Unique,
2205                                       ntStatus));
2206                     }
2207                 }
2208                 else
2209                 {
2210
2211                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2212                                   AFS_TRACE_LEVEL_ERROR,
2213                                   "AFSProcessCreate (%p) Failed to evaluate object %wZ FID %08lX-%08lX-%08lX-%08lX Status %08lX\n",
2214                                   Irp,
2215                                   &pDirEntry->NameInformation.FileName,
2216                                   pObjectInfo->FileId.Cell,
2217                                   pObjectInfo->FileId.Volume,
2218                                   pObjectInfo->FileId.Vnode,
2219                                   pObjectInfo->FileId.Unique,
2220                                   ntStatus));
2221                 }
2222
2223                 try_return( ntStatus);
2224             }
2225
2226             ClearFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_NOT_EVALUATED);
2227         }
2228
2229         ASSERT( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2230                 AFSIsEqualFID( &pParentObjectInfo->FileId, &pObjectInfo->ParentFileId));
2231
2232         //
2233         // We may have raced and the Fcb is already created
2234         //
2235
2236         //
2237         // Allocate and initialize the Fcb for the file.
2238         //
2239
2240         ntStatus = AFSInitFcb( pDirEntry);
2241
2242         *Fcb = pObjectInfo->Fcb;
2243
2244         if( !NT_SUCCESS( ntStatus))
2245         {
2246
2247             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2248                           AFS_TRACE_LEVEL_ERROR,
2249                           "AFSProcessCreate (%p) Failed to initialize fcb %wZ Status %08lX\n",
2250                           Irp,
2251                           FullFileName,
2252                           ntStatus));
2253
2254             try_return( ntStatus);
2255         }
2256
2257         ntStatus = STATUS_SUCCESS;
2258
2259         //
2260         // Increment the open count on this Fcb
2261         //
2262
2263         lCount = InterlockedIncrement( &(*Fcb)->OpenReferenceCount);
2264
2265         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2266                       AFS_TRACE_LEVEL_VERBOSE,
2267                       "AFSProcessCreate Increment count on Fcb %p Cnt %d\n",
2268                       *Fcb,
2269                       lCount));
2270
2271         bReleaseFcb = TRUE;
2272
2273         //
2274         // Initialize the Ccb for the file.
2275         //
2276
2277         ntStatus = AFSInitCcb( Ccb,
2278                                pDirEntry,
2279                                *pDesiredAccess,
2280                                0);
2281
2282         if( !NT_SUCCESS( ntStatus))
2283         {
2284
2285             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2286                           AFS_TRACE_LEVEL_ERROR,
2287                           "AFSProcessCreate (%p) Failed to initialize ccb %wZ Status %08lX\n",
2288                           Irp,
2289                           FullFileName,
2290                           ntStatus));
2291
2292             try_return( ntStatus);
2293         }
2294
2295         bAllocatedCcb = TRUE;
2296
2297         //
2298         // If this is a file, update the headers filesizes.
2299         //
2300
2301         if( (*Fcb)->Header.NodeTypeCode == AFS_FILE_FCB)
2302         {
2303
2304             //
2305             // Update the sizes with the information passed in
2306             //
2307
2308             (*Fcb)->Header.AllocationSize.QuadPart  = pObjectInfo->AllocationSize.QuadPart;
2309             (*Fcb)->Header.FileSize.QuadPart        = pObjectInfo->EndOfFile.QuadPart;
2310             (*Fcb)->Header.ValidDataLength.QuadPart = pObjectInfo->EndOfFile.QuadPart;
2311
2312             //
2313             // Notify the system of the addition
2314             //
2315
2316             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2317                                             *Ccb,
2318                                             (ULONG)FILE_NOTIFY_CHANGE_FILE_NAME,
2319                                             (ULONG)FILE_ACTION_ADDED);
2320
2321             (*Fcb)->NPFcb->Specific.File.ExtentsRequestStatus = STATUS_SUCCESS;
2322         }
2323         else if( (*Fcb)->Header.NodeTypeCode == AFS_DIRECTORY_FCB)
2324         {
2325
2326             //
2327             // This is a new directory node so indicate it has been enumerated
2328             //
2329
2330             SetFlag( pObjectInfo->Flags, AFS_OBJECT_FLAGS_DIRECTORY_ENUMERATED);
2331
2332             //
2333             // And the parent directory entry
2334             //
2335
2336             KeQuerySystemTime( &pParentObjectInfo->ChangeTime);
2337
2338             //
2339             // Notify the system of the addition
2340             //
2341
2342             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2343                                             *Ccb,
2344                                             (ULONG)FILE_NOTIFY_CHANGE_DIR_NAME,
2345                                             (ULONG)FILE_ACTION_ADDED);
2346         }
2347         else if( (*Fcb)->Header.NodeTypeCode == AFS_MOUNT_POINT_FCB ||
2348                  (*Fcb)->Header.NodeTypeCode == AFS_SYMBOLIC_LINK_FCB ||
2349                  (*Fcb)->Header.NodeTypeCode == AFS_DFS_LINK_FCB ||
2350                  (*Fcb)->Header.NodeTypeCode == AFS_INVALID_FCB)
2351         {
2352
2353             //
2354             // And the parent directory entry
2355             //
2356
2357             KeQuerySystemTime( &pParentObjectInfo->ChangeTime);
2358
2359             //
2360             // Notify the system of the addition
2361             //
2362
2363             AFSFsRtlNotifyFullReportChange( pParentObjectInfo,
2364                                             *Ccb,
2365                                             (ULONG)FILE_NOTIFY_CHANGE_DIR_NAME,
2366                                             (ULONG)FILE_ACTION_ADDED);
2367         }
2368
2369         //
2370         // Save off the access for the open
2371         //
2372
2373         IoSetShareAccess( *pDesiredAccess,
2374                           usShareAccess,
2375                           pFileObject,
2376                           &(*Fcb)->ShareAccess);
2377
2378         lCount = InterlockedIncrement( &(*Fcb)->OpenHandleCount);
2379
2380         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2381                       AFS_TRACE_LEVEL_VERBOSE,
2382                       "AFSProcessCreate Increment handle count on Fcb %p Cnt %d\n",
2383                       (*Fcb),
2384                       lCount));
2385
2386         //
2387         // Increment the open reference and handle on the parent node
2388         //
2389
2390         lCount = InterlockedIncrement( &pParentObjectInfo->Specific.Directory.ChildOpenHandleCount);
2391
2392         AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2393                       AFS_TRACE_LEVEL_VERBOSE,
2394                       "AFSProcessCreate Increment child open handle count on Parent object %p Cnt %d\n",
2395                       pParentObjectInfo,
2396                       lCount));
2397
2398         lCount = InterlockedIncrement( &pParentObjectInfo->Specific.Directory.ChildOpenReferenceCount);
2399
2400         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2401                       AFS_TRACE_LEVEL_VERBOSE,
2402                       "AFSProcessCreate Increment child open ref count on Parent object %p Cnt %d\n",
2403                       pParentObjectInfo,
2404                       lCount));
2405
2406         if( ulOptions & FILE_DELETE_ON_CLOSE)
2407         {
2408
2409             //
2410             // Mark it for delete on close
2411             //
2412
2413             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2414                           AFS_TRACE_LEVEL_VERBOSE,
2415                           "AFSProcessCreate (%p) Setting PENDING_DELETE flag in DirEntry %p Name %wZ\n",
2416                           Irp,
2417                           pDirEntry,
2418                           FullFileName));
2419
2420             SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_PENDING_DELETE);
2421         }
2422
2423         //
2424         // Indicate the object is locked in the service
2425         //
2426
2427         SetFlag( pObjectInfo->Flags, AFS_OBJECT_HELD_IN_SERVICE);
2428
2429         //
2430         // Return the open result for this file
2431         //
2432
2433         Irp->IoStatus.Information = FILE_CREATED;
2434
2435 try_exit:
2436
2437         //
2438         // If we created the Fcb we need to release the resources
2439         //
2440
2441         if( bReleaseFcb)
2442         {
2443
2444             if( !NT_SUCCESS( ntStatus))
2445             {
2446                 //
2447                 // Decrement the open count on this Fcb
2448                 //
2449
2450                 lCount = InterlockedDecrement( &(*Fcb)->OpenReferenceCount);
2451
2452                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2453                               AFS_TRACE_LEVEL_VERBOSE,
2454                               "AFSProcessCreate Decrement count on Fcb %p Cnt %d\n",
2455                               *Fcb,
2456                               lCount));
2457             }
2458
2459             AFSReleaseResource( &(*Fcb)->NPFcb->Resource);
2460         }
2461
2462         if ( bFileCreated)
2463         {
2464
2465             //
2466             // Decrement the reference added during initialization of the DE
2467             // AFSInitCcb allocates its own reference count.
2468             //
2469
2470             lCount = InterlockedDecrement( &pDirEntry->DirOpenReferenceCount);
2471
2472             AFSDbgTrace(( AFS_SUBSYSTEM_DIRENTRY_REF_COUNTING,
2473                           AFS_TRACE_LEVEL_VERBOSE,
2474                           "AFSProcessCreate Decrement count on %wZ DE %p Cnt %d\n",
2475                           &pDirEntry->NameInformation.FileName,
2476                           pDirEntry,
2477                           lCount));
2478
2479             ASSERT( lCount >= 0);
2480         }
2481
2482         if( !NT_SUCCESS( ntStatus))
2483         {
2484
2485             if( bFileCreated)
2486             {
2487
2488                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2489                               AFS_TRACE_LEVEL_VERBOSE,
2490                               "AFSProcessCreate Create failed, removing DE %p from parent object %p Status %08lX\n",
2491                               pDirEntry,
2492                               pParentObjectInfo,
2493                               ntStatus));
2494
2495                 //
2496                 // Remove the dir entry from the parent
2497                 //
2498
2499                 AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
2500                                 TRUE);
2501
2502                 SetFlag( pDirEntry->Flags, AFS_DIR_ENTRY_DELETED);
2503
2504                 AFSNotifyDelete( pDirEntry,
2505                                  AuthGroup,
2506                                  FALSE);
2507
2508                 //
2509                 // Pull the directory entry from the parent
2510                 //
2511
2512                 AFSRemoveDirNodeFromParent( pParentObjectInfo,
2513                                             pDirEntry,
2514                                             FALSE); // Leave it in the enum list so the worker cleans it up
2515
2516                 //
2517                 // Tag the parent as needing verification
2518                 //
2519
2520                 SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
2521
2522                 pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
2523
2524                 AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
2525             }
2526
2527             if( bAllocatedCcb)
2528             {
2529
2530                 AFSRemoveCcb( NULL,
2531                               *Ccb);
2532             }
2533
2534             //
2535             // Fcb will be freed by AFSPrimaryVolumeWorker thread
2536             //
2537
2538             *Fcb = NULL;
2539
2540             *Ccb = NULL;
2541         }
2542     }
2543
2544     return ntStatus;
2545 }
2546
2547 NTSTATUS
2548 AFSOpenTargetDirectory( IN PIRP Irp,
2549                         IN AFSVolumeCB *VolumeCB,
2550                         IN AFSDirectoryCB *ParentDirectoryCB,
2551                         IN AFSDirectoryCB *TargetDirectoryCB,
2552                         IN UNICODE_STRING *TargetName,
2553                         OUT AFSFcb **Fcb,
2554                         OUT AFSCcb **Ccb)
2555 {
2556     UNREFERENCED_PARAMETER(VolumeCB);
2557     NTSTATUS ntStatus = STATUS_SUCCESS;
2558     PFILE_OBJECT pFileObject = NULL;
2559     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2560     PACCESS_MASK pDesiredAccess = NULL;
2561     USHORT usShareAccess;
2562     BOOLEAN bAllocatedCcb = FALSE;
2563     BOOLEAN bReleaseFcb = FALSE;
2564     AFSObjectInfoCB *pParentObject = NULL;
2565     AFSObjectInfoCB *pGrandParentObject = NULL;
2566     UNICODE_STRING uniTargetName;
2567     LONG lCount;
2568
2569     __Enter
2570     {
2571
2572         pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
2573         usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
2574
2575         pFileObject = pIrpSp->FileObject;
2576
2577         AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2578                       AFS_TRACE_LEVEL_VERBOSE,
2579                       "AFSOpenTargetDirectory (%p) Processing file %wZ\n",
2580                       Irp,
2581                       TargetName));
2582
2583         pParentObject = ParentDirectoryCB->ObjectInformation;
2584
2585         if( pParentObject->FileType != AFS_FILE_TYPE_DIRECTORY)
2586         {
2587
2588             try_return( ntStatus = STATUS_INVALID_PARAMETER);
2589         }
2590
2591         //
2592         // Make sure we have an Fcb for the access
2593
2594         //
2595         // Allocate and initialize the Fcb for the file.
2596         //
2597
2598         ntStatus = AFSInitFcb( ParentDirectoryCB);
2599
2600         *Fcb = pParentObject->Fcb;
2601
2602         if( !NT_SUCCESS( ntStatus))
2603         {
2604
2605             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2606                           AFS_TRACE_LEVEL_ERROR,
2607                           "AFSOpenTargetDirectory (%p) Failed to initialize fcb %wZ Status %08lX\n",
2608                           Irp,
2609                           &ParentDirectoryCB->NameInformation.FileName,
2610                           ntStatus));
2611
2612             try_return( ntStatus);
2613         }
2614
2615         ntStatus = STATUS_SUCCESS;
2616
2617         //
2618         // Increment the open count on this Fcb
2619         //
2620
2621         lCount = InterlockedIncrement( &pParentObject->Fcb->OpenReferenceCount);
2622
2623         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2624                       AFS_TRACE_LEVEL_VERBOSE,
2625                       "AFSOpenTargetDirectory Increment count on Fcb %p Cnt %d\n",
2626                       pParentObject->Fcb,
2627                       lCount));
2628
2629         bReleaseFcb = TRUE;
2630
2631         //
2632         // If there are current opens on the Fcb, check the access.
2633         //
2634
2635         if( pParentObject->Fcb->OpenHandleCount > 0)
2636         {
2637
2638             ntStatus = IoCheckShareAccess( *pDesiredAccess,
2639                                            usShareAccess,
2640                                            pFileObject,
2641                                            &pParentObject->Fcb->ShareAccess,
2642                                            FALSE);
2643
2644             if( !NT_SUCCESS( ntStatus))
2645             {
2646
2647                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2648                               AFS_TRACE_LEVEL_ERROR,
2649                               "AFSOpenTargetDirectory (%p) Access check failure %wZ Status %08lX\n",
2650                               Irp,
2651                               &ParentDirectoryCB->NameInformation.FileName,
2652                               ntStatus));
2653
2654                 try_return( ntStatus);
2655             }
2656         }
2657
2658         //
2659         // Initialize the Ccb for the file.
2660         //
2661
2662         ntStatus = AFSInitCcb( Ccb,
2663                                ParentDirectoryCB,
2664                                *pDesiredAccess,
2665                                0);
2666
2667         if( !NT_SUCCESS( ntStatus))
2668         {
2669
2670             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2671                           AFS_TRACE_LEVEL_ERROR,
2672                           "AFSOpenTargetDirectory (%p) Failed to initialize ccb %wZ Status %08lX\n",
2673                           Irp,
2674                           &ParentDirectoryCB->NameInformation.FileName,
2675                           ntStatus));
2676
2677             try_return( ntStatus);
2678         }
2679
2680         bAllocatedCcb = TRUE;
2681
2682         if( TargetDirectoryCB != NULL &&
2683             FsRtlAreNamesEqual( &TargetDirectoryCB->NameInformation.FileName,
2684                                 TargetName,
2685                                 FALSE,
2686                                 NULL))
2687         {
2688
2689             Irp->IoStatus.Information = FILE_EXISTS;
2690
2691             uniTargetName = TargetDirectoryCB->NameInformation.FileName;
2692         }
2693         else
2694         {
2695
2696             Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
2697
2698             uniTargetName = *TargetName;
2699         }
2700
2701         //
2702         // Update the filename in the fileobject for rename processing
2703         //
2704
2705         RtlCopyMemory( pFileObject->FileName.Buffer,
2706                        uniTargetName.Buffer,
2707                        uniTargetName.Length);
2708
2709         pFileObject->FileName.Length = uniTargetName.Length;
2710
2711         //
2712         // OK, update the share access on the fileobject
2713         //
2714
2715         if( pParentObject->Fcb->OpenHandleCount > 0)
2716         {
2717
2718             IoUpdateShareAccess( pFileObject,
2719                                  &pParentObject->Fcb->ShareAccess);
2720         }
2721         else
2722         {
2723
2724             //
2725             // Set the access
2726             //
2727
2728             IoSetShareAccess( *pDesiredAccess,
2729                               usShareAccess,
2730                               pFileObject,
2731                               &pParentObject->Fcb->ShareAccess);
2732         }
2733
2734         lCount = InterlockedIncrement( &pParentObject->Fcb->OpenHandleCount);
2735
2736         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2737                       AFS_TRACE_LEVEL_VERBOSE,
2738                       "AFSOpenTargetDirectory Increment handle count on Fcb %p Cnt %d\n",
2739                       pParentObject->Fcb,
2740                       lCount));
2741
2742         //
2743         // Increment the open reference and handle on the parent node
2744         //
2745
2746         if( BooleanFlagOn( pParentObject->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
2747         {
2748
2749             pGrandParentObject = AFSFindObjectInfo( pParentObject->VolumeCB,
2750                                                     &pParentObject->ParentFileId,
2751                                                     TRUE);
2752
2753             if ( pGrandParentObject)
2754             {
2755
2756                 lCount = InterlockedIncrement( &pGrandParentObject->Specific.Directory.ChildOpenHandleCount);
2757
2758                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2759                               AFS_TRACE_LEVEL_VERBOSE,
2760                               "AFSOpenTargetDirectory Increment child open handle count on Parent object %p Cnt %d\n",
2761                               pGrandParentObject,
2762                               lCount));
2763
2764                 lCount = InterlockedIncrement( &pGrandParentObject->Specific.Directory.ChildOpenReferenceCount);
2765
2766                 AFSDbgTrace(( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
2767                               AFS_TRACE_LEVEL_VERBOSE,
2768                               "AFSOpenTargetDirectory Increment child open ref count on Parent object %p Cnt %d\n",
2769                               pGrandParentObject,
2770                               lCount));
2771
2772                 AFSReleaseObjectInfo( &pGrandParentObject);
2773             }
2774         }
2775
2776 try_exit:
2777
2778         if( bReleaseFcb)
2779         {
2780
2781             if( !NT_SUCCESS( ntStatus))
2782             {
2783                 //
2784                 // Decrement the open count on this Fcb
2785                 //
2786
2787                 lCount = InterlockedDecrement( &pParentObject->Fcb->OpenReferenceCount);
2788
2789                 AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2790                               AFS_TRACE_LEVEL_VERBOSE,
2791                               "AFSOpenTargetDirectory Decrement count on Fcb %p Cnt %d\n",
2792                               pParentObject->Fcb,
2793                               lCount));
2794             }
2795
2796             AFSReleaseResource( &pParentObject->Fcb->NPFcb->Resource);
2797         }
2798
2799         if( !NT_SUCCESS( ntStatus))
2800         {
2801
2802             if( bAllocatedCcb)
2803             {
2804
2805                 AFSRemoveCcb( NULL,
2806                               *Ccb);
2807             }
2808
2809             *Ccb = NULL;
2810
2811             //
2812             // Fcb will be freed by AFSPrimaryVolumeWorker thread
2813             //
2814
2815             *Fcb = NULL;
2816         }
2817     }
2818
2819     return ntStatus;
2820 }
2821
2822 NTSTATUS
2823 AFSProcessOpen( IN PIRP Irp,
2824                 IN GUID *AuthGroup,
2825                 IN AFSVolumeCB *VolumeCB,
2826                 IN AFSDirectoryCB *ParentDirCB,
2827                 IN AFSDirectoryCB *DirectoryCB,
2828                 IN BOOLEAN bOpenedReparsePoint,
2829                 OUT AFSFcb **Fcb,
2830                 OUT AFSCcb **Ccb)
2831 {
2832     UNREFERENCED_PARAMETER(VolumeCB);
2833     NTSTATUS ntStatus = STATUS_SUCCESS;
2834     PFILE_OBJECT pFileObject = NULL;
2835     PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp);
2836     PACCESS_MASK pDesiredAccess = NULL;
2837     USHORT usShareAccess;
2838     BOOLEAN bAllocatedCcb = FALSE, bReleaseFcb = FALSE;
2839     ULONG ulOptions = 0;
2840     AFSFileOpenCB   stOpenCB;
2841     AFSFileOpenResultCB stOpenResultCB;
2842     ULONG       ulResultLen = 0;
2843     AFSObjectInfoCB *pParentObjectInfo = NULL;
2844     AFSObjectInfoCB *pObjectInfo = NULL;
2845     ULONG       ulFileAccess = 0;
2846     AFSFileAccessReleaseCB stReleaseFileAccess;
2847     LONG lCount;
2848
2849     __Enter
2850     {
2851
2852         pDesiredAccess = &pIrpSp->Parameters.Create.SecurityContext->DesiredAccess;
2853         usShareAccess = pIrpSp->Parameters.Create.ShareAccess;
2854
2855         pFileObject = pIrpSp->FileObject;
2856
2857         pParentObjectInfo = ParentDirCB->ObjectInformation;
2858
2859         pObjectInfo = DirectoryCB->ObjectInformation;
2860
2861         ASSERT( BooleanFlagOn( pObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID) &&
2862                 AFSIsEqualFID( &pParentObjectInfo->FileId, &pObjectInfo->ParentFileId));
2863
2864         //
2865         // Check if the entry is pending a deletion
2866         //
2867
2868         if( BooleanFlagOn( DirectoryCB->Flags, AFS_DIR_ENTRY_PENDING_DELETE))
2869         {
2870
2871             ntStatus = STATUS_DELETE_PENDING;
2872
2873             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2874                           AFS_TRACE_LEVEL_ERROR,
2875                           "AFSProcessOpen (%p) Entry pending delete %wZ Status %08lX\n",
2876                           Irp,
2877                           &DirectoryCB->NameInformation.FileName,
2878                           ntStatus));
2879
2880             try_return( ntStatus);
2881         }
2882
2883         //
2884         // Extract out the options
2885         //
2886
2887         ulOptions = pIrpSp->Parameters.Create.Options;
2888
2889         //
2890         // Check if we should go and retrieve updated information for the node
2891         //
2892
2893         ntStatus = AFSValidateEntry( DirectoryCB,
2894                                      AuthGroup,
2895                                      bOpenedReparsePoint,
2896                                      TRUE);
2897
2898         if( !NT_SUCCESS( ntStatus))
2899         {
2900
2901             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2902                           AFS_TRACE_LEVEL_ERROR,
2903                           "AFSProcessOpen (%p) Failed to validate entry %wZ Status %08lX\n",
2904                           Irp,
2905                           &DirectoryCB->NameInformation.FileName,
2906                           ntStatus));
2907
2908             try_return( ntStatus);
2909         }
2910
2911         //
2912         // If this is marked for delete on close then be sure we can delete the entry
2913         //
2914
2915         if( BooleanFlagOn( ulOptions, FILE_DELETE_ON_CLOSE))
2916         {
2917
2918             ntStatus = AFSNotifyDelete( DirectoryCB,
2919                                         AuthGroup,
2920                                         TRUE);
2921
2922             if( !NT_SUCCESS( ntStatus))
2923             {
2924
2925                 ntStatus = STATUS_CANNOT_DELETE;
2926
2927                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2928                               AFS_TRACE_LEVEL_ERROR,
2929                               "AFSProcessOpen (%p) Cannot delete entry %wZ marked for delete on close Status %08lX\n",
2930                               Irp,
2931                               &DirectoryCB->NameInformation.FileName,
2932                               ntStatus));
2933
2934                 try_return( ntStatus);
2935             }
2936         }
2937
2938         //
2939         // Be sure we have an Fcb for the current object
2940         //
2941
2942         ntStatus = AFSInitFcb( DirectoryCB);
2943
2944         if( !NT_SUCCESS( ntStatus))
2945         {
2946
2947             AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2948                           AFS_TRACE_LEVEL_ERROR,
2949                           "AFSProcessOpen (%p) Failed to init fcb on %wZ Status %08lX\n",
2950                           Irp,
2951                           &DirectoryCB->NameInformation.FileName,
2952                           ntStatus));
2953
2954             try_return( ntStatus);
2955         }
2956
2957         ntStatus = STATUS_SUCCESS;
2958
2959         //
2960         // AFSInitFcb returns the Fcb resource held
2961         //
2962
2963         bReleaseFcb = TRUE;
2964
2965         //
2966         // Increment the open count on this Fcb
2967         //
2968
2969         lCount = InterlockedIncrement( &pObjectInfo->Fcb->OpenReferenceCount);
2970
2971         AFSDbgTrace(( AFS_SUBSYSTEM_FCB_REF_COUNTING,
2972                       AFS_TRACE_LEVEL_VERBOSE,
2973                       "AFSProcessOpen Increment2 count on Fcb %p Cnt %d\n",
2974                       pObjectInfo->Fcb,
2975                       lCount));
2976
2977         //
2978         // Check access on the entry
2979         //
2980
2981         if( pObjectInfo->Fcb->OpenHandleCount > 0)
2982         {
2983
2984             ntStatus = IoCheckShareAccess( *pDesiredAccess,
2985                                            usShareAccess,
2986                                            pFileObject,
2987                                            &pObjectInfo->Fcb->ShareAccess,
2988                                            FALSE);
2989
2990             if( !NT_SUCCESS( ntStatus))
2991             {
2992
2993                 AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
2994                               AFS_TRACE_LEVEL_ERROR,
2995                               "AFSProcessOpen (%p) Failed to check share access on %wZ Status %08lX\n",
2996                               Irp,
2997                               &DirectoryCB->NameInformation.FileName,
2998                               ntStatus));
2999
3000                 try_return( ntStatus);
3001             }
3002         }
3003
3004         //
3005         // Additional checks
3006         //
3007
3008         if( pObjectInfo->Fcb->Header.NodeTypeCode == AFS_FILE_FCB)
3009         {
3010
3011             //
3012             // If the caller is asking for write access then try to flush the image section
3013             //
3014
3015             if( FlagOn( *pDesiredAccess, FILE_WRITE_DATA) ||
3016                 BooleanFlagOn(ulOptions, FILE_DELETE_ON_CLOSE))
3017             {
3018
3019                 BOOLEAN bMmFlushed;
3020
3021                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3022                               AFS_TRACE_LEVEL_VERBOSE,
3023                               "AFSProcessOpen Acquiring Fcb SectionObject lock %p EXCL %08lX\n",
3024                               &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3025                               PsGetCurrentThread()));
3026
3027                 AFSAcquireExcl( &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3028                                 TRUE);
3029
3030                 __try
3031                 {
3032
3033                     bMmFlushed = MmFlushImageSection( &pObjectInfo->Fcb->NPFcb->SectionObjectPointers,
3034                                                       MmFlushForWrite);
3035                 }
3036                 __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
3037                 {
3038
3039                     bMmFlushed = FALSE;
3040
3041                     ntStatus = GetExceptionCode();
3042
3043                     AFSDbgTrace(( 0,
3044                                   0,
3045                                   "EXCEPTION - AFSProcessOpen MmFlushImageSection failed FID %08lX-%08lX-%08lX-%08lX Status 0x%08lX\n",
3046                                   pObjectInfo->FileId.Cell,
3047                                   pObjectInfo->FileId.Volume,
3048                                   pObjectInfo->FileId.Vnode,
3049                                   pObjectInfo->FileId.Unique,
3050                                   ntStatus));
3051                 }
3052
3053                 AFSDbgTrace(( AFS_SUBSYSTEM_LOCK_PROCESSING|AFS_SUBSYSTEM_SECTION_OBJECT,
3054                               AFS_TRACE_LEVEL_VERBOSE,
3055                               "AFSProcessOpen Releasing Fcb SectionObject lock %p EXCL %08lX\n",
3056                               &pObjectInfo->Fcb->NPFcb->SectionObjectResource,
3057                               PsGetCurrentThread()));
3058
3059                 AFSReleaseResource( &pObjectInfo->Fcb->NPFcb->SectionObjectResource);
3060
3061                 if ( !bMmFlushed)
3062                 {
3063
3064                     ntStatus = BooleanFlagOn(ulOptions, FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE :
3065                                                                             STATUS_SHARING_VIOLATION;
3066
3067                     AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING,
3068                                   AFS_TRACE_LEVEL_ERROR,
3069                                   "AFSProcessOpen (%p) Failed to flush image section %wZ Status %08lX\n",
3070                                   Irp,
3071                                   &DirectoryCB->NameInformation.FileName,
3072                                   ntStatus));
3073
3074                     try_return( ntStatus);
3075                 }
3076             }
3077
3078             if( BooleanFlagOn( ulOptions, FILE_DIRECTORY_FILE))
3079             {