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