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