xref: /reactos/drivers/filesystems/udfs/create.cpp (revision 34593d93)
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
7 *
8 * File: Create.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 *   Contains code to handle the "Create"/"Open" dispatch entry point.
14 *
15 *************************************************************************/
16 
17 #include            "udffs.h"
18 
19 #define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
20 
21 // define the file specific bug-check id
22 #define         UDF_BUG_CHECK_ID                UDF_FILE_CREATE
23 
24 #define         MEM_USABS_TAG                   "US_Abs"
25 #define         MEM_USLOC_TAG                   "US_Loc"
26 #define         MEM_USOBJ_TAG                   "US_Obj"
27 
28 #define UDF_LOG_CREATE_DISPOSITION
29 
30 /*************************************************************************
31 *
32 * Function: UDFCreate()
33 *
34 * Description:
35 *   The I/O Manager will invoke this routine to handle a create/open
36 *   request
37 *
38 * Expected Interrupt Level (for execution) :
39 *
40 *  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
41 *   to be deferred to a worker thread context)
42 *
43 * Return Value: STATUS_SUCCESS/Error
44 *
45 *************************************************************************/
46 NTSTATUS
47 NTAPI
48 UDFCreate(
49     PDEVICE_OBJECT          DeviceObject,       // the logical volume device object
50     PIRP                    Irp)                // I/O Request Packet
51 {
52     NTSTATUS            RC = STATUS_SUCCESS;
53     PtrUDFIrpContext    PtrIrpContext;
54     BOOLEAN             AreWeTopLevel = FALSE;
55 
56     TmPrint(("UDFCreate:\n"));
57 
58     FsRtlEnterFileSystem();
59     ASSERT(DeviceObject);
60     ASSERT(Irp);
61 
62     // sometimes, we may be called here with the device object representing
63     //  the file system (instead of the device object created for a logical
64     //  volume. In this case, there is not much we wish to do (this create
65     //  typically will happen 'cause some process has to open the FSD device
66     //  object so as to be able to send an IOCTL to the FSD)
67 
68     //  All of the logical volume device objects we create have a device
69     //  extension whereas the device object representing the FSD has no
70     //  device extension. This seems like a good enough method to identify
71     //  between the two device objects ...
72     if (UDFIsFSDevObj(DeviceObject)) {
73         // this is an open of the FSD itself
74         Irp->IoStatus.Status = RC;
75         Irp->IoStatus.Information = FILE_OPENED;
76 
77         IoCompleteRequest(Irp, IO_NO_INCREMENT);
78         FsRtlExitFileSystem();
79         return(RC);
80     }
81 
82     // set the top level context
83     AreWeTopLevel = UDFIsIrpTopLevel(Irp);
84 
85     _SEH2_TRY {
86 
87         // get an IRP context structure and issue the request
88         PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
89         if(PtrIrpContext) {
90             RC = UDFCommonCreate(PtrIrpContext, Irp);
91         } else {
92             RC = STATUS_INSUFFICIENT_RESOURCES;
93             Irp->IoStatus.Status = RC;
94             Irp->IoStatus.Information = 0;
95             // complete the IRP
96             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
97         }
98 
99     } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
100 
101         RC = UDFExceptionHandler(PtrIrpContext, Irp);
102 
103         UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
104     } _SEH2_END;
105 
106     if (AreWeTopLevel) {
107         IoSetTopLevelIrp(NULL);
108     }
109 
110     AdPrint(("UDFCreate: %x\n", RC));
111 
112     FsRtlExitFileSystem();
113 
114     return(RC);
115 
116 } // end UDFCreate()
117 
118 /*
119  */
120 VOID
121 __fastcall
122 UDFReleaseResFromCreate(
123     IN PERESOURCE* PagingIoRes,
124     IN PERESOURCE* Res1,
125     IN PERESOURCE* Res2
126     )
127 {
128     if(*PagingIoRes) {
129         UDFReleaseResource(*PagingIoRes);
130         (*PagingIoRes) = NULL;
131     }
132     if(*Res1) {
133         UDFReleaseResource(*Res1);
134         (*Res1) = NULL;
135     }
136     if(*Res2) {
137         UDFReleaseResource(*Res2);
138         (*Res2) = NULL;
139     }
140 } // end UDFReleaseResFromCreate()
141 
142 /*
143  */
144 VOID
145 __fastcall
146 UDFAcquireParent(
147     IN PUDF_FILE_INFO RelatedFileInfo,
148     IN PERESOURCE* Res1,
149     IN PERESOURCE* Res2
150     )
151 {
152     if(RelatedFileInfo->Fcb &&
153        RelatedFileInfo->Fcb->ParentFcb) {
154 
155         UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->ParentFcb->NTRequiredFCB);
156         UDFAcquireResourceExclusive((*Res2) = &(RelatedFileInfo->Fcb->ParentFcb->NTRequiredFCB->MainResource),TRUE);
157     }
158 
159     UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB);
160     UDFAcquireResourceExclusive((*Res1) = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
161 
162     UDFInterlockedIncrement((PLONG)&(RelatedFileInfo->Fcb->ReferenceCount));
163     UDFInterlockedIncrement((PLONG)&(RelatedFileInfo->Dloc->CommonFcb->CommonRefCount));
164     UDFReferenceFile__(RelatedFileInfo);
165     ASSERT_REF(RelatedFileInfo->Fcb->ReferenceCount >= RelatedFileInfo->RefCount);
166 } // end UDFAcquireParent()
167 
168 /*************************************************************************
169 *
170 * Function: UDFCommonCreate()
171 *
172 * Description:
173 *   The actual work is performed here. This routine may be invoked in one'
174 *   of the two possible contexts:
175 *   (a) in the context of a system worker thread
176 *   (b) in the context of the original caller
177 *
178 * Expected Interrupt Level (for execution) :
179 *
180 *  IRQL_PASSIVE_LEVEL
181 *
182 * Return Value: STATUS_SUCCESS/Error
183 *
184 *************************************************************************/
185 NTSTATUS
186 UDFCommonCreate(
187     PtrUDFIrpContext                PtrIrpContext,
188     PIRP                            Irp
189     )
190 {
191     NTSTATUS                    RC = STATUS_SUCCESS;
192     PIO_STACK_LOCATION          IrpSp = NULL;
193     PIO_SECURITY_CONTEXT        PtrSecurityContext = NULL;
194     PFILE_OBJECT                PtrNewFileObject = NULL;
195     PFILE_OBJECT                PtrRelatedFileObject = NULL;
196     LONGLONG                    AllocationSize;     // if we create a new file
197     PFILE_FULL_EA_INFORMATION   PtrExtAttrBuffer = NULL;
198     ULONG                       RequestedOptions;
199     ULONG                       RequestedDisposition;
200     USHORT                      FileAttributes;
201     USHORT                      TmpFileAttributes;
202     USHORT                      ShareAccess;
203     ULONG                       ExtAttrLength = 0;
204     ACCESS_MASK                 DesiredAccess;
205     PACCESS_STATE               AccessState;
206 
207     PVCB                        Vcb = NULL;
208     _SEH2_VOLATILE BOOLEAN      AcquiredVcb = FALSE;
209     BOOLEAN                     OpenExisting = FALSE;
210     PERESOURCE                  Res1 = NULL;
211     PERESOURCE                  Res2 = NULL;
212     PERESOURCE                  PagingIoRes = NULL;
213 
214 //  BOOLEAN                     DirectoryOnlyRequested;
215 //  BOOLEAN                     FileOnlyRequested;
216 //  BOOLEAN                     NoBufferingSpecified;
217     BOOLEAN                     WriteThroughRequested;
218     BOOLEAN                     DeleteOnCloseSpecified;
219 //  BOOLEAN                     NoExtAttrKnowledge;
220 //  BOOLEAN                     CreateTreeConnection = FALSE;
221 //  BOOLEAN                     OpenByFileId;
222 
223     // Are we dealing with a page file?
224     BOOLEAN                     PageFileManipulation;
225     // Is this open for a target directory (used in rename operations)?
226     BOOLEAN                     OpenTargetDirectory;
227     // Should we ignore case when attempting to locate the object?
228     BOOLEAN                     IgnoreCase;
229 
230     PtrUDFCCB                   PtrRelatedCCB = NULL, PtrNewCcb = NULL;
231     PtrUDFFCB                   PtrRelatedFCB = NULL, PtrNewFcb = NULL;
232     PtrUDFNTRequiredFCB         NtReqFcb;
233 
234     ULONG                       ReturnedInformation = 0;
235 
236     UNICODE_STRING              TargetObjectName;
237     UNICODE_STRING              RelatedObjectName;
238 
239     UNICODE_STRING              AbsolutePathName;    // '\aaa\cdf\fff\rrrr.tre:s'
240     UNICODE_STRING              LocalPath;           // '\aaa\cdf'
241     UNICODE_STRING              CurName;             // 'cdf'
242     UNICODE_STRING              TailName;            // 'fff\rrrr.tre:s'
243     UNICODE_STRING              LastGoodName;        // it depends...
244     UNICODE_STRING              LastGoodTail;        // it depends...
245     UNICODE_STRING              StreamName;          // ':s'
246 
247     PUDF_FILE_INFO              RelatedFileInfo;
248     PUDF_FILE_INFO              OldRelatedFileInfo = NULL;
249     PUDF_FILE_INFO              NewFileInfo = NULL;
250     PUDF_FILE_INFO              LastGoodFileInfo = NULL;
251     PWCHAR                      TmpBuffer;
252     ULONG                       TreeLength = 0;
253 //    ULONG                       i = 0;
254 
255     BOOLEAN                     StreamOpen = FALSE;
256     BOOLEAN                     StreamExists = FALSE;
257     BOOLEAN                     RestoreVCBOpenCounter = FALSE;
258     BOOLEAN                     RestoreShareAccess = FALSE;
259     PWCHAR                      TailNameBuffer = NULL;
260     ULONG                       SNameIndex = 0;
261 
262     TmPrint(("UDFCommonCreate:\n"));
263 
264     ASSERT(PtrIrpContext);
265     ASSERT(Irp);
266 
267     _SEH2_TRY {
268 
269         AbsolutePathName.Buffer =
270         LocalPath.Buffer = NULL;
271         //  If we were called with our file system device object instead of a
272         //  volume device object, just complete this request with STATUS_SUCCESS.
273         if (!(PtrIrpContext->TargetDeviceObject->DeviceExtension)) {
274 
275             ReturnedInformation = FILE_OPENED;
276             try_return(RC = STATUS_SUCCESS);
277         }
278 
279         AbsolutePathName.Length = AbsolutePathName.MaximumLength =
280         LocalPath.Length = LocalPath.MaximumLength = 0;
281         // First, get a pointer to the current I/O stack location
282         IrpSp = IoGetCurrentIrpStackLocation(Irp);
283         ASSERT(IrpSp);
284 
285         // If the caller cannot block, post the request to be handled
286         //  asynchronously
287         if (!(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK)) {
288             // We must defer processing of this request since we could
289             //  block anytime while performing the create/open ...
290             ASSERT(FALSE);
291             RC = UDFPostRequest(PtrIrpContext, Irp);
292             try_return(RC);
293         }
294 
295         // Now, we can obtain the parameters specified by the user.
296         //  Note that the file object is the new object created by the
297         //  I/O Manager in anticipation that this create/open request
298         //  will succeed.
299         PtrNewFileObject     = IrpSp->FileObject;
300         TargetObjectName     = PtrNewFileObject->FileName;
301         PtrRelatedFileObject = PtrNewFileObject->RelatedFileObject;
302 
303         // If a related file object is present, get the pointers
304         //  to the CCB and the FCB for the related file object
305         if (PtrRelatedFileObject) {
306             PtrRelatedCCB = (PtrUDFCCB)(PtrRelatedFileObject->FsContext2);
307             ASSERT(PtrRelatedCCB);
308             ASSERT(PtrRelatedCCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_CCB);
309             // each CCB in turn points to a FCB
310             PtrRelatedFCB = PtrRelatedCCB->Fcb;
311             ASSERT(PtrRelatedFCB);
312             ASSERT((PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB)
313                  ||(PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB));
314             RelatedObjectName = PtrRelatedFileObject->FileName;
315             if (!(RelatedObjectName.Length) || (RelatedObjectName.Buffer[0] != L'\\')) {
316                 if(PtrRelatedFCB->FCBName)
317                     RelatedObjectName = PtrRelatedFCB->FCBName->ObjectName;
318             }
319         }
320 
321         // Allocation size is only used if a new file is created
322         //  or a file is superseded.
323         AllocationSize = Irp->Overlay.AllocationSize.QuadPart;
324 
325         // Get a ptr to the supplied security context
326         PtrSecurityContext = IrpSp->Parameters.Create.SecurityContext;
327         AccessState = PtrSecurityContext->AccessState;
328 
329         // The desired access can be obtained from the SecurityContext
330         DesiredAccess = PtrSecurityContext->DesiredAccess;
331 
332         // Two values are supplied in the Create.Options field:
333         //  (a) the actual user supplied options
334         //  (b) the create disposition
335         RequestedOptions = (IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS);
336 
337         // The file disposition is packed with the user options ...
338         //  Disposition includes FILE_SUPERSEDE, FILE_OPEN_IF, etc.
339         RequestedDisposition = (IrpSp->Parameters.Create.Options >> 24);// & 0xFF;
340 
341 //#ifdef UDF_LOG_CREATE_DISPOSITION
342         switch(RequestedDisposition) {
343         case FILE_SUPERSEDE:
344             AdPrint(("    Dispos: FILE_SUPERSEDE\n"));
345             break;
346         case FILE_OPEN:
347             AdPrint(("    Dispos: FILE_OPEN\n"));
348             break;
349         case FILE_CREATE:
350             AdPrint(("    Dispos: FILE_CREATE\n"));
351             break;
352         case FILE_OPEN_IF:
353             AdPrint(("    Dispos: FILE_OPEN_IF\n"));
354             break;
355         case FILE_OVERWRITE:
356             AdPrint(("    Dispos: FILE_OVERWRITE\n"));
357             break;
358         case FILE_OVERWRITE_IF:
359             AdPrint(("    Dispos: FILE_OVERWRITE_IF\n"));
360             break;
361         default:
362             AdPrint(("    Dispos: *** Unknown ***\n"));
363             break;
364         }
365 //#endif // UDF_LOG_CREATE_DISPOSITION
366 
367         FileAttributes  = (USHORT)(IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS);
368         ShareAccess = IrpSp->Parameters.Create.ShareAccess;
369 
370         // If the FSD does not support EA manipulation, we might return
371         //  invalid parameter if the following are supplied.
372         //  EA arguments are only used if a new file is created or a file is
373         //  superseded
374 
375         // But some applications _require_ EA support
376         //  (Notepad... rather strange, isn't it ?)
377 
378         //         So, for such stupid ones
379         // !!! We shall ignore these parameters !!!
380 
381 //        PtrExtAttrBuffer = (struct _FILE_FULL_EA_INFORMATION *) Irp->AssociatedIrp.SystemBuffer;
382 //        ExtAttrLength    = IrpSp->Parameters.Create.EaLength;
383 
384         // Get the options supplied by the user
385 
386 #define OpenForBackup (RequestedOptions & FILE_OPEN_FOR_BACKUP_INTENT)
387         // User specifies that returned object MUST be a directory.
388         //  Lack of presence of this flag does not mean it *cannot* be a
389         //  directory *unless* FileOnlyRequested is set (see below)
390 
391         //  Presence of the flag however, does require that the returned object be
392         //  a directory (container) object.
393 #define DirectoryOnlyRequested (RequestedOptions & FILE_DIRECTORY_FILE)
394 
395         // User specifies that returned object MUST NOT be a directory.
396         //  Lack of presence of this flag does not mean it *cannot* be a
397         //  file *unless* DirectoryOnlyRequested is set (see above).
398 
399         //  Presence of the flag however does require that the returned object be
400         //  a simple file (non-container) object.
401 #define FileOnlyRequested (RequestedOptions & FILE_NON_DIRECTORY_FILE)
402 
403         // We cannot cache the file if the following flag is set.
404         //  However, things do get a little bit interesting if caching
405         //  has been already initiated due to a previous open ...
406         //  (maintaining consistency then becomes a little bit more
407         //  of a headache - see read/write file descriptions)
408 #define NoBufferingSpecified (RequestedOptions & FILE_NO_INTERMEDIATE_BUFFERING)
409 
410         // Write-through simply means that the FSD must *not* return from
411         //  a user write request until the data has been flushed to secondary
412         //  storage (either to disks directly connected to the node or across
413         //  the network in the case of a redirector)
414         WriteThroughRequested = (RequestedOptions & FILE_WRITE_THROUGH) ? TRUE : FALSE;
415 
416 #define SequentialIoRequested   (RequestedOptions & FILE_SEQUENTIAL_ONLY ? TRUE : FALSE)
417 
418         // Not all of the native file system implementations support
419         //  the delete-on-close option. All this means is that after the
420         //  last close on the FCB has been performed, the FSD should
421         //  delete the file. It simply saves the caller from issuing a
422         //  separate delete request. Also, some FSD implementations might choose
423         //  to implement a Windows NT idiosyncratic behavior wherein we
424         //  could create such "delete-on-close" marked files under directories
425         //  marked for deletion. Ordinarily, a FSD will not allow us to create
426         //  a new file under a directory that has been marked for deletion.
427         DeleteOnCloseSpecified = (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE) ? TRUE : FALSE;
428 
429         if(DeleteOnCloseSpecified) {
430             AdPrint(("    DeleteOnClose\n"));
431         }
432 
433 #define NoExtAttrKnowledge /*(RequestedOptions & FILE_NO_EA_KNOWLEDGE) ?*/ TRUE /*: FALSE*/
434 
435         // The following flag is only used by the LAN Manager redirector
436         //  to  initiate a "new mapping" to a remote share. Typically,
437         //  a FSD will not see this flag (especially disk based FSD's)
438         // CreateTreeConnection = (RequestedOptions & FILE_CREATE_TREE_CONNECTION) ? TRUE : FALSE;
439 
440         // The NTFS file system for exmaple supports the OpenByFileId option.
441         //  The FSD may also be able to associate a unique numerical ID with
442         //  an on-disk object. The caller would get this ID in a "query file
443         //  information" call.
444 
445         //  Later, the caller might decide to reopen the object, this time
446         //  though it may supply the FSD with the file identifier instead of
447         //  a file/path name.
448 #define OpenByFileId (RequestedOptions & FILE_OPEN_BY_FILE_ID)
449 
450         // Are we dealing with a page file?
451         PageFileManipulation = (IrpSp->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
452 
453         // The open target directory flag is used as part of the sequence of
454         //  operations performed by the I/O Manager is response to a file/dir
455         //  rename operation. See the explanation in the book for details.
456         OpenTargetDirectory = (IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY) ? TRUE : FALSE;
457 
458         // If the FSD supports case-sensitive file name checks, we may
459         //  choose to honor the following flag ...
460         IgnoreCase = (IrpSp->Flags & SL_CASE_SENSITIVE) ? FALSE : TRUE;
461 
462         // Ensure that the operation has been directed to a valid VCB ...
463         Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
464         ASSERT(Vcb);
465         ASSERT(Vcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB);
466 //        Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
467 
468         WriteThroughRequested = WriteThroughRequested ||
469                                 (Vcb->CompatFlags & UDF_VCB_IC_FORCE_WRITE_THROUGH);
470 
471         //  Do some preliminary checks to make sure the operation is supported.
472         //  We fail in the following cases immediately.
473         //      - Open a paging file.
474         //      - Open a file with Eas.
475         if(PageFileManipulation) {
476             ReturnedInformation = 0;
477             AdPrint(("Can't create a page file\n"));
478             try_return(RC = STATUS_ACCESS_DENIED);
479         }
480         if(ExtAttrLength) {
481             ReturnedInformation = 0;
482             AdPrint(("Can't create file with EAs\n"));
483             try_return(RC = STATUS_EAS_NOT_SUPPORTED);
484         }
485 
486         UDFFlushTryBreak(Vcb);
487 
488         if (Vcb->SoftEjectReq) {
489             AdPrint(("    Eject requested\n"));
490             ReturnedInformation = FILE_DOES_NOT_EXIST;
491             try_return(RC = STATUS_FILE_INVALID);
492         }
493 
494         // If the volume has been locked, fail the request
495         if ((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) &&
496             (Vcb->VolumeLockPID != GetCurrentPID())) {
497             AdPrint(("    Volume is locked\n"));
498             RC = STATUS_ACCESS_DENIED;
499             try_return(RC);
500         }
501         // We need EXCLUSIVE access to Vcb to avoid parallel calls to UDFVerifyVcb()
502         UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
503         AcquiredVcb = TRUE;
504 
505         // Disk based file systems might decide to verify the logical volume
506         //  (if required and only if removable media are supported) at this time
507         RC = UDFVerifyVcb(PtrIrpContext,Vcb);
508         if(!NT_SUCCESS(RC))
509             try_return(RC);
510 
511         UDFConvertExclusiveToSharedLite(&(Vcb->VCBResource));
512 
513         ASSERT(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED);
514 
515         // We fail in the following cases for Read-Only volumes
516         //      - Open a target directory.
517         //      - Create a file.
518         if(
519            (
520            ((Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) &&
521             (Vcb->CompatFlags & UDF_VCB_IC_DIRTY_RO))
522 #ifndef UDF_READ_ONLY_BUILD
523             || (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)
524 #endif //UDF_READ_ONLY_BUILD
525             ) &&
526             (DeleteOnCloseSpecified ||
527              OpenTargetDirectory ||
528              (RequestedDisposition == FILE_CREATE) ||
529              (RequestedDisposition == FILE_OVERWRITE) ||
530              (RequestedDisposition == FILE_OVERWRITE_IF) ||
531              (RequestedDisposition == FILE_SUPERSEDE) ||
532              AllocationSize) ) {
533             ReturnedInformation = 0;
534             AdPrint(("    Write protected or dirty\n"));
535             try_return(RC = STATUS_MEDIA_WRITE_PROTECTED);
536         }
537 
538 /*        if(DesiredAccess & (FILE_READ_EA | FILE_WRITE_EA)) {
539             ReturnedInformation = 0;
540             AdPrint(("    EAs not supported\n"));
541             try_return(RC = STATUS_ACCESS_DENIED);
542         }*/
543 
544         // ****************
545         // If a Volume open is requested, satisfy it now
546         // ****************
547         if (!(PtrNewFileObject->FileName.Length) && (!PtrRelatedFileObject ||
548               (PtrRelatedFCB->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB))) {
549 
550             BOOLEAN UndoLock = FALSE;
551 
552             AdPrint(("  Opening Volume\n"));
553             // If the supplied file name is NULL *and* either there exists
554             //  no related file object *or* if a related file object was supplied
555             //  but it too refers to a previously opened instance of a logical
556             //  volume, this open must be for a logical volume.
557 
558             //  Note: the FSD might decide to do "special" things (whatever they
559             //  might be) in response to an open request for the logical volume.
560 
561             //  Logical volume open requests are done primarily to get/set volume
562             //  information, lock the volume, dismount the volume (using the IOCTL
563             //  FSCTL_DISMOUNT_VOLUME) etc.
564 
565             //  If a volume open is requested, perform checks to ensure that
566             //  invalid options have not also been specified ...
567             if ((OpenTargetDirectory) || (PtrExtAttrBuffer)) {
568                 try_return(RC = STATUS_INVALID_PARAMETER);
569             }
570 
571             if (DirectoryOnlyRequested) {
572                 // a volume is not a directory
573                 try_return(RC = STATUS_NOT_A_DIRECTORY);
574             }
575 
576 #ifndef UDF_READ_ONLY_BUILD
577             if (DeleteOnCloseSpecified) {
578                 // delete volume.... hmm
579                 try_return(RC = STATUS_CANNOT_DELETE);
580             }
581 
582             if ((RequestedDisposition != FILE_OPEN) && (RequestedDisposition != FILE_OPEN_IF)) {
583                 // cannot create a new volume, I'm afraid ...
584                 ReturnedInformation = FILE_DOES_NOT_EXIST;
585                 try_return(RC = STATUS_ACCESS_DENIED);
586             }
587 #endif //UDF_READ_ONLY_BUILD
588 
589             UDFPrint(("  ShareAccess %x, DesiredAccess %x\n", ShareAccess, DesiredAccess));
590 /*
591             if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE)) &&
592                !(DesiredAccess & (FILE_GENERIC_WRITE & ~SYNCHRONIZE)) &&
593                 (ShareAccess & FILE_SHARE_READ) ) {
594 */
595             if(!(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) &&
596                 (ShareAccess & FILE_SHARE_READ) ) {
597                 UDFPrint(("  R/O volume open\n"));
598             } else {
599 
600                 UDFPrint(("  R/W volume open\n"));
601                 if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) {
602                     UDFPrint(("  media-ro\n"));
603                     try_return(RC = STATUS_MEDIA_WRITE_PROTECTED);
604                 }
605             }
606 
607             if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE)) &&
608                !(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) &&
609                 (ShareAccess & FILE_SHARE_READ) ) {
610                 // do nothing
611             } else {
612 
613                 if(!(ShareAccess & FILE_SHARE_READ) ||
614                     (DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) ) {
615                     // As soon as OpenVolume flushes the volume
616                     // we should complete all pending requests (Close)
617 
618                     UDFPrint(("  set UDF_IRP_CONTEXT_FLUSH2_REQUIRED\n"));
619                     PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLUSH2_REQUIRED;
620 
621 /*
622                     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
623                     UDFReleaseResource(&(Vcb->VCBResource));
624                     AcquiredVcb = FALSE;
625 
626                     if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
627                         UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
628                     }
629 #ifdef UDF_DELAYED_CLOSE
630                     UDFCloseAllDelayed(Vcb);
631 #endif //UDF_DELAYED_CLOSE
632 
633                     UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
634                     AcquiredVcb = TRUE;
635                     UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
636 */
637                 }
638             }
639 
640             // If the user does not want to share write or delete then we will try
641             // and take out a lock on the volume.
642             if(!(ShareAccess & (FILE_SHARE_WRITE | FILE_SHARE_DELETE))) {
643                 // Do a quick check here for handles on exclusive open.
644                 if ((Vcb->VCBHandleCount) &&
645                     !(ShareAccess & FILE_SHARE_READ)) {
646                     // Sharing violation
647                     UDFPrint(("  !FILE_SHARE_READ + open handles (%d)\n", Vcb->VCBHandleCount));
648                     try_return(RC = STATUS_SHARING_VIOLATION);
649                 }
650                 if(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_FLUSH2_REQUIRED) {
651 
652                     UDFPrint(("  perform flush\n"));
653                     PtrIrpContext->IrpContextFlags &= ~UDF_IRP_CONTEXT_FLUSH2_REQUIRED;
654 
655                     UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
656                     UDFReleaseResource(&(Vcb->VCBResource));
657                     AcquiredVcb = FALSE;
658 
659                     if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) {
660                         UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
661                     }
662 #ifdef UDF_DELAYED_CLOSE
663                     UDFCloseAllDelayed(Vcb);
664 #endif //UDF_DELAYED_CLOSE
665 
666                     UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
667                     AcquiredVcb = TRUE;
668                     UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
669 
670                     UDFFlushLogicalVolume(NULL, NULL, Vcb);
671 
672                     if((ShareAccess & FILE_SHARE_READ) &&
673                        ((Vcb->VCBOpenCount - UDF_RESIDUAL_REFERENCE) != (Vcb->VCBOpenCountRO))) {
674                         UDFPrint(("  FILE_SHARE_READ + R/W handles: %d(%d) -> STATUS_SHARING_VIOLATION ?\n",
675                             Vcb->VCBOpenCount - UDF_RESIDUAL_REFERENCE,
676                             Vcb->VCBOpenCountRO));
677                         /* we shall not check it here, let System do it in IoCheckShareAccess() */
678                         //try_return(RC = STATUS_SHARING_VIOLATION);
679                     }
680                 }
681                 // Lock the volume
682                 if(!(ShareAccess & FILE_SHARE_READ)) {
683                     UDFPrint(("  set Lock\n"));
684                     Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_LOCKED;
685                     Vcb->VolumeLockFileObject = PtrNewFileObject;
686                     UndoLock = TRUE;
687                 } else
688                 if(DesiredAccess & ((GENERIC_WRITE | FILE_GENERIC_WRITE) & ~(SYNCHRONIZE | READ_CONTROL))) {
689                     UDFPrint(("  set UDF_IRP_CONTEXT_FLUSH_REQUIRED\n"));
690                     PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLUSH_REQUIRED;
691                 }
692             }
693 
694             PtrNewFcb = (PtrUDFFCB)Vcb;
695             ASSERT(!(PtrNewFcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE));
696 
697             RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
698             if (!NT_SUCCESS(RC))
699                 goto op_vol_accs_dnd;
700 
701             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
702             if(PtrNewCcb) PtrNewCcb->CCBFlags |= UDF_CCB_VOLUME_OPEN;
703             // Check _Security_
704             RC = UDFCheckAccessRights(NULL, AccessState, Vcb->RootDirFCB, PtrNewCcb, DesiredAccess, ShareAccess);
705             if (!NT_SUCCESS(RC)) {
706                 AdPrint(("    Access violation (Volume)\n"));
707                 goto op_vol_accs_dnd;
708             }
709             // Check _ShareAccess_
710             RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
711             if(!NT_SUCCESS(RC)) {
712                 AdPrint(("    Sharing violation (Volume)\n"));
713 op_vol_accs_dnd:
714                 if(UndoLock) {
715                     Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
716                     Vcb->VolumeLockFileObject = NULL;
717                 }
718                 try_return(RC);
719             }
720 
721 //      NoBufferingSpecified = TRUE;  See #define above
722             RequestedOptions |= FILE_NO_INTERMEDIATE_BUFFERING;
723 
724             ReturnedInformation = FILE_OPENED;
725             UDFNotifyVolumeEvent(PtrNewFileObject, FSRTL_VOLUME_LOCK);
726             try_return(RC);
727         }
728 
729         if((Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) &&
730            (!(Vcb->CompatFlags & UDF_VCB_IC_SHOW_BLANK_CD) || UDFGlobalData.AutoFormatCount)) {
731             ReturnedInformation = 0;
732             AdPrint(("    Can't open anything on blank volume ;)\n"));
733             try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND);
734         }
735 
736         if(UdfIllegalFcbAccess(Vcb,DesiredAccess)) {
737             ReturnedInformation = 0;
738             AdPrint(("    Illegal share access\n"));
739             try_return(RC = STATUS_ACCESS_DENIED);
740         }
741         // we could mount blank R/RW media in order to allow
742         // user-mode applications to get access with Write privileges
743         ASSERT(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED);
744 
745         // we should check appropriate privilege if OpenForBackup requested
746         if(OpenForBackup) {
747             if (!SeSinglePrivilegeCheck(SeExports->SeBackupPrivilege, UserMode)) {
748                 try_return(RC = STATUS_PRIVILEGE_NOT_HELD);
749             }
750         }
751 
752         // The FSD might wish to implement the open-by-id option. The "id"
753         //  is some unique numerical representation of the on-disk object.
754         //  The caller then therefore give us this file id and the FSD
755         //  should be completely capable of "opening" the object (it must
756         //  exist since the caller received an id for the object from the
757         //  FSD in a "query file" call ...
758 
759         //  If the file has been deleted in the meantime, we'll return
760         //  "not found"
761 
762         // ****************
763         // Open by FileID
764         // ****************
765         if (OpenByFileId) {
766             // perform the open ...
767             PUNICODE_STRING TmpPath;
768             LONGLONG Id;
769 
770             UDFPrint(("    open by File ID\n"));
771             if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
772                 ReturnedInformation = 0;
773                 AdPrint(("    Can't open by FileID on blank volume ;)\n"));
774                 try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND);
775             }
776 
777             if (TargetObjectName.Length != sizeof(FILE_ID)) {
778                 AdPrint(("    Invalid file ID\n"));
779                 try_return(RC = STATUS_INVALID_PARAMETER);
780             }
781             Id = *((FILE_ID*)(TargetObjectName.Buffer));
782             AdPrint(("  Opening by ID %8.8x%8.8x\n", (ULONG)(Id>>32), (ULONG)Id));
783             if ((RequestedDisposition != FILE_OPEN) &&
784                 (RequestedDisposition != FILE_OPEN_IF)) {
785                 AdPrint(("    Illegal disposition for ID open\n"));
786                 try_return(RC = STATUS_ACCESS_DENIED);
787             }
788 
789             RC = UDFGetOpenParamsByFileId(Vcb, Id, &TmpPath, &IgnoreCase);
790             if(!NT_SUCCESS(RC)) {
791                 AdPrint(("    ID open failed\n"));
792                 try_return(RC);
793             }
794             // simulate absolute path open
795 /*            if(!NT_SUCCESS(RC = MyInitUnicodeString(&TargetObjectName, L"")) ||
796                !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&TargetObjectName, TmpPath, MEM_USABS_TAG))) {*/
797             if(!NT_SUCCESS(RC = MyCloneUnicodeString(&TargetObjectName, TmpPath))) {
798                 AdPrint(("    Init String failed\n"));
799                 try_return(RC);
800             }
801             //ASSERT(TargetObjectName.Buffer);
802             AbsolutePathName = TargetObjectName;
803             PtrRelatedFileObject = NULL;
804         } else
805         // ****************
806         // Relative open
807         // ****************
808         // Now determine the starting point from which to begin the parsing
809         if (PtrRelatedFileObject) {
810             // We have a user supplied related file object.
811             //  This implies a "relative" open i.e. relative to the directory
812             //  represented by the related file object ...
813 
814             UDFPrint(("    PtrRelatedFileObject %x, FCB %x\n", PtrRelatedFileObject, PtrRelatedFCB));
815             //  Note: The only purpose FSD implementations ever have for
816             //  the related file object is to determine whether this
817             //  is a relative open or not. At all other times (including
818             //  during I/O operations), this field is meaningless from
819             //  the FSD's perspective.
820             if (!(PtrRelatedFCB->FCBFlags & UDF_FCB_DIRECTORY)) {
821                 // we must have a directory as the "related" object
822                 RC = STATUS_INVALID_PARAMETER;
823                 AdPrint(("    Related object must be a directory\n"));
824                 AdPrint(("    Flags %x\n", PtrRelatedFCB->FCBFlags));
825                 _SEH2_TRY {
826                     AdPrint(("    ObjName %x, ", PtrRelatedFCB->FCBName->ObjectName));
827                     AdPrint(("    Name %S\n", PtrRelatedFCB->FCBName->ObjectName.Buffer));
828                 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
829                     AdPrint(("    exception when printing name\n"));
830                 } _SEH2_END;
831                 try_return(RC);
832             }
833 
834             // So we have a directory, ensure that the name begins with
835             //  a "\" i.e. begins at the root and does *not* begin with a "\\"
836             //  NOTE: This is just an example of the kind of path-name string
837             //  validation that a FSD must do. Although the remainder of
838             //  the code may not include such checks, any commercial
839             //  FSD *must* include such checking (no one else, including
840             //  the I/O Manager will perform checks on the FSD's behalf)
841             if (!(RelatedObjectName.Length) || (RelatedObjectName.Buffer[0] != L'\\')) {
842                 AdPrint(("    Wrong pathname (1)\n"));
843                 RC = STATUS_INVALID_PARAMETER;
844                 try_return(RC);
845             }
846             // similarly, if the target file name starts with a "\", it
847             //  is wrong since the target file name can no longer be absolute
848             ASSERT(TargetObjectName.Buffer || !TargetObjectName.Length);
849             if (TargetObjectName.Length && (TargetObjectName.Buffer[0] == L'\\')) {
850                 AdPrint(("    Wrong pathname (2)\n"));
851                 RC = STATUS_INVALID_PARAMETER;
852                 try_return(RC);
853             }
854             // Create an absolute path-name. We could potentially use
855             //  the absolute path-name if we cache previously opened
856             //  file/directory object names.
857 /*            if(!NT_SUCCESS(RC = MyInitUnicodeString(&AbsolutePathName, L"")) ||
858                !NT_SUCCESS(RC MyAppendUnicodeStringToStringTag(&AbsolutePathName, &RelatedObjectName, MEM_USABS_TAG)))*/
859             if(!NT_SUCCESS(RC = MyCloneUnicodeString(&AbsolutePathName, &RelatedObjectName)))
860                 try_return(RC);
861             if(RelatedObjectName.Length &&
862                 (RelatedObjectName.Buffer[ (RelatedObjectName.Length/sizeof(WCHAR)) - 1 ] != L'\\')) {
863                 RC = MyAppendUnicodeToString(&AbsolutePathName, L"\\");
864                 if(!NT_SUCCESS(RC)) try_return(RC);
865             }
866             if(!AbsolutePathName.Length ||
867                 (AbsolutePathName.Buffer[ (AbsolutePathName.Length/sizeof(WCHAR)) - 1 ] != L'\\')) {
868                 ASSERT(TargetObjectName.Buffer);
869                 if(TargetObjectName.Length && TargetObjectName.Buffer[0] != L'\\') {
870                     RC = MyAppendUnicodeToString(&AbsolutePathName, L"\\");
871                     if(!NT_SUCCESS(RC)) try_return(RC);
872                 }
873             }
874             //ASSERT(TargetObjectName.Buffer);
875             RC = MyAppendUnicodeStringToStringTag(&AbsolutePathName, &TargetObjectName, MEM_USABS_TAG);
876             if(!NT_SUCCESS(RC))
877                 try_return(RC);
878 
879         } else {
880         // ****************
881         // Absolute open
882         // ****************
883             // The suplied path-name must be an absolute path-name i.e.
884             //  starting at the root of the file system tree
885             UDFPrint(("    Absolute open\n"));
886             ASSERT(TargetObjectName.Buffer);
887             if (!TargetObjectName.Length || TargetObjectName.Buffer[0] != L'\\') {
888                 AdPrint(("    Wrong target name (1)\n"));
889                 try_return(RC = STATUS_INVALID_PARAMETER);
890             }
891 /*            if(!NT_SUCCESS(RC = MyInitUnicodeString(&AbsolutePathName, L"")) ||
892                !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&AbsolutePathName, &TargetObjectName, MEM_USABS_TAG)))*/
893             ASSERT(TargetObjectName.Buffer);
894             if(!NT_SUCCESS(RC = MyCloneUnicodeString(&AbsolutePathName, &TargetObjectName)))
895                 try_return(RC);
896         }
897         // Win 32 protection :)
898         if ((AbsolutePathName.Length >= sizeof(WCHAR)*2) &&
899             (AbsolutePathName.Buffer[1] == L'\\') &&
900             (AbsolutePathName.Buffer[0] == L'\\')) {
901 
902             //  If there are still two beginning backslashes, the name is bogus.
903             if ((AbsolutePathName.Length > 2*sizeof(WCHAR)) &&
904                 (AbsolutePathName.Buffer[2] == L'\\')) {
905                 AdPrint(("    Wrong target name (2)\n"));
906                 try_return (RC = STATUS_OBJECT_NAME_INVALID);
907             }
908             //  Slide the name down in the buffer.
909             RtlMoveMemory( AbsolutePathName.Buffer,
910                            AbsolutePathName.Buffer + 1,
911                            AbsolutePathName.Length ); // .Length includes
912                                                       //      NULL-terminator
913             AbsolutePathName.Length -= sizeof(WCHAR);
914         }
915         if ( (AbsolutePathName.Length > sizeof(WCHAR) ) &&
916             (AbsolutePathName.Buffer[ (AbsolutePathName.Length/sizeof(WCHAR)) - 1 ] == L'\\') ) {
917 
918             AbsolutePathName.Length -= sizeof(WCHAR);
919         }
920         // TERMINATOR (2)   ;)
921         AbsolutePathName.Buffer[AbsolutePathName.Length/sizeof(WCHAR)] = 0;
922 
923         // Sometimes W2000 decides to duplicate handle of
924         // already opened File/Dir. In this case it sends us
925         // RelatedFileObject & specifies zero-filled RelativePath
926         if(!TargetObjectName.Length) {
927             TargetObjectName = AbsolutePathName;
928             OpenExisting = TRUE;
929         }
930         //ASSERT(TargetObjectName.Buffer);
931 
932         // ****************
933         //  First, check if the caller simply wishes to open the Root
934         //  of the file system tree.
935         // ****************
936         if (AbsolutePathName.Length == sizeof(WCHAR)) {
937             AdPrint(("  Opening RootDir\n"));
938             // this is an open of the root directory, ensure that the caller
939             // has not requested a file only
940             if (FileOnlyRequested || (RequestedDisposition == FILE_SUPERSEDE) ||
941                  (RequestedDisposition == FILE_OVERWRITE) ||
942                  (RequestedDisposition == FILE_OVERWRITE_IF)) {
943                 AdPrint(("    Can't overwrite RootDir\n"));
944                 RC = STATUS_FILE_IS_A_DIRECTORY;
945                 try_return(RC);
946             }
947 
948 #if 0
949             CollectStatistics(Vcb, MetaDataReads);
950 #endif
951 
952             if (DeleteOnCloseSpecified) {
953                 // delete RootDir.... rather strange idea... I dislike it
954                 AdPrint(("    Can't delete RootDir\n"));
955                 try_return(RC = STATUS_CANNOT_DELETE);
956             }
957 
958             PtrNewFcb = Vcb->RootDirFCB;
959             RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
960             if(!NT_SUCCESS(RC)) try_return(RC);
961 //            DbgPrint("UDF: Open/Create RootDir : ReferenceCount %x\n",PtrNewFcb->ReferenceCount);
962             UDFReferenceFile__(PtrNewFcb->FileInfo);
963             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
964             TreeLength = 1;
965 
966             RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
967             if(!NT_SUCCESS(RC)) {
968                 AdPrint(("    Access/Sharing violation (RootDir)\n"));
969                 try_return(RC);
970             }
971 
972             ReturnedInformation = FILE_OPENED;
973 
974             try_return(RC);
975         } // end of OpenRootDir
976 
977         _SEH2_TRY {
978             AdPrint(("    Opening file %ws %8.8x\n",AbsolutePathName.Buffer, PtrNewFileObject));
979         } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
980             AdPrint(("    Exception when printing FN\n"));
981         } _SEH2_END;
982         // ****************
983         // Check if we have DuplicateHandle (or Reopen) request
984         // ****************
985         if(OpenExisting) {
986 
987 //            BrutePoint();
988             // We don't handle OpenTargetDirectory in this case
989             if(OpenTargetDirectory)
990                 try_return(RC = STATUS_INVALID_PARAMETER);
991 
992             // Init environment to simulate normal open procedure behavior
993 /*            if(!NT_SUCCESS(RC = MyInitUnicodeString(&LocalPath, L"")) ||
994                !NT_SUCCESS(RC = MyAppendUnicodeStringToStringTag(&LocalPath, &TargetObjectName, MEM_USLOC_TAG)))*/
995             ASSERT(TargetObjectName.Buffer);
996             if(!NT_SUCCESS(RC = MyCloneUnicodeString(&LocalPath, &TargetObjectName)))
997                 try_return(RC);
998 
999             ASSERT(PtrRelatedFCB);
1000             RelatedFileInfo = PtrRelatedFCB->FileInfo;
1001 
1002             RC = STATUS_SUCCESS;
1003             NewFileInfo =
1004             LastGoodFileInfo = RelatedFileInfo;
1005 
1006             RelatedFileInfo =
1007             OldRelatedFileInfo = RelatedFileInfo->ParentFile;
1008             PtrRelatedFCB = PtrRelatedFCB->ParentFcb;
1009             // prevent releasing parent structures
1010             UDFAcquireParent(RelatedFileInfo, &Res1, &Res2);
1011             TreeLength++;
1012 
1013             if(Res1) UDFReleaseResource(Res1);
1014             if(Res2) UDFReleaseResource(Res2);
1015 
1016             UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB);
1017             UDFAcquireResourceExclusive(Res2 = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
1018             PtrNewFcb = NewFileInfo->Fcb;
1019 
1020             UDF_CHECK_PAGING_IO_RESOURCE(PtrNewFcb->NTRequiredFCB);
1021             UDFAcquireResourceExclusive(Res1 = &(PtrNewFcb->NTRequiredFCB->MainResource),TRUE);
1022             UDFReferenceFile__(NewFileInfo);
1023             TreeLength++;
1024 
1025             goto AlreadyOpened;
1026         }
1027 
1028         if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) {
1029             ReturnedInformation = 0;
1030             AdPrint(("    Can't open File on blank volume ;)\n"));
1031             ReturnedInformation = FILE_DOES_NOT_EXIST;
1032             try_return(RC = STATUS_OBJECT_NAME_NOT_FOUND);
1033         }
1034 
1035         //AdPrint(("    Opening file %ws %8.8x\n",AbsolutePathName.Buffer, PtrNewFileObject));
1036 
1037         if(AbsolutePathName.Length > UDF_X_PATH_LEN*sizeof(WCHAR)) {
1038             try_return(RC = STATUS_OBJECT_NAME_INVALID);
1039         }
1040 
1041         // validate path specified
1042         // (sometimes we can see here very strange characters ;)
1043         if(!UDFIsNameValid(&AbsolutePathName, &StreamOpen, &SNameIndex)) {
1044             AdPrint(("    Absolute path is not valid\n"));
1045             try_return(RC = STATUS_OBJECT_NAME_INVALID);
1046         }
1047         if(StreamOpen && !UDFStreamsSupported(Vcb)) {
1048             ReturnedInformation = FILE_DOES_NOT_EXIST;
1049             try_return(RC = STATUS_OBJECT_NAME_INVALID);
1050         }
1051 
1052         RC = MyInitUnicodeString(&LocalPath, L"");
1053         if(!NT_SUCCESS(RC))
1054             try_return(RC);
1055         if (PtrRelatedFileObject) {
1056             // Our "start directory" is the one identified
1057             // by the related file object
1058             RelatedFileInfo = PtrRelatedFCB->FileInfo;
1059             if(RelatedFileInfo != Vcb->RootDirFCB->FileInfo) {
1060                 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(PtrRelatedFCB->FCBName->ObjectName), MEM_USLOC_TAG);
1061                 if(!NT_SUCCESS(RC))
1062                     try_return(RC);
1063             }
1064             if(TargetObjectName.Buffer != AbsolutePathName.Buffer) {
1065                 ASSERT(TargetObjectName.Buffer);
1066                 if(!NT_SUCCESS(RC = MyCloneUnicodeString(&TailName, &TargetObjectName))) {
1067                     AdPrint(("    Init String 'TargetObjectName' failed\n"));
1068                     try_return(RC);
1069                 }
1070                 TailNameBuffer = TailName.Buffer;
1071             } else {
1072                 TailName = AbsolutePathName;
1073             }
1074         } else {
1075             // Start at the root of the file system
1076             RelatedFileInfo = Vcb->RootDirFCB->FileInfo;
1077             TailName = AbsolutePathName;
1078         }
1079 
1080         if(StreamOpen) {
1081             StreamName = AbsolutePathName;
1082             StreamName.Buffer += SNameIndex;
1083             StreamName.Length -= (USHORT)SNameIndex*sizeof(WCHAR);
1084             // if StreamOpen specified & stream name starts with NULL character
1085             // we should create Stream Dir at first
1086             TailName.Length -= (AbsolutePathName.Length - (USHORT)SNameIndex*sizeof(WCHAR));
1087             AbsolutePathName.Length = (USHORT)SNameIndex*sizeof(WCHAR);
1088         }
1089         CurName.MaximumLength = TailName.MaximumLength;
1090 
1091         RC = STATUS_SUCCESS;
1092         LastGoodName.Length = 0;
1093         LastGoodFileInfo = RelatedFileInfo;
1094         // reference RelatedObject to prevent releasing parent structures
1095         UDFAcquireParent(RelatedFileInfo, &Res1, &Res2);
1096         TreeLength++;
1097 
1098         // go into a loop parsing the supplied name
1099 
1100         //  Note that we may have to "open" intermediate directory objects
1101         //  while traversing the path. We should __try to reuse existing code
1102         //  whenever possible therefore we should consider using a common
1103         //  open routine regardless of whether the open is on behalf of the
1104         //  caller or an intermediate (internal) open performed by the driver.
1105 
1106         // ****************
1107         // now we'll parse path to desired file
1108         // ****************
1109 
1110         while (TRUE) {
1111 
1112             // remember last 'good' ('good' means NO ERRORS before) path tail
1113             if(NT_SUCCESS(RC)) {
1114                 LastGoodTail = TailName;
1115                 while(LastGoodTail.Buffer[0] == L'\\') {
1116                     LastGoodTail.Buffer++;
1117                     LastGoodTail.Length -= sizeof(WCHAR);
1118                 }
1119             }
1120             // get next path part...
1121             TmpBuffer = TailName.Buffer;
1122             TailName.Buffer = UDFDissectName(TailName.Buffer,&(CurName.Length) );
1123             TailName.Length -= (USHORT)((ULONG_PTR)(TailName.Buffer) - (ULONG_PTR)TmpBuffer);
1124             CurName.Buffer = TailName.Buffer - CurName.Length;
1125             CurName.Length *= sizeof(WCHAR);
1126             CurName.MaximumLength = CurName.Length + sizeof(WCHAR);
1127             // check if we have already opened the component before last one
1128             // in this case OpenTargetDir request will be served in a special
1129             // way...
1130             if(OpenTargetDirectory && NT_SUCCESS(RC) && !TailName.Length) {
1131                 // check if we should open SDir..
1132                 if(!StreamOpen ||
1133                    (TailName.Buffer[0]!=L':')) {
1134                     // no, we should not. Continue with OpenTargetDir
1135                     break;
1136                 }
1137             }
1138 
1139             if( CurName.Length &&
1140                (NT_SUCCESS(RC) || !StreamOpen)) {
1141                 // ...wow! non-zero! try to open!
1142                 if(!NT_SUCCESS(RC)) {
1143                     AdPrint(("    Error opening path component\n"));
1144                     // we haven't reached last name part... hm..
1145                     // probably, the path specified is invalid..
1146                     // or we had a hard error... What else can we do ?
1147                     // Only say ..CK OFF !!!!
1148                     if(RC == STATUS_OBJECT_NAME_NOT_FOUND)
1149                         RC = STATUS_OBJECT_PATH_NOT_FOUND;
1150                     ReturnedInformation = FILE_DOES_NOT_EXIST;
1151                     try_return(RC);
1152                 }
1153 
1154                 ASSERT_REF(RelatedFileInfo->Fcb->ReferenceCount >= RelatedFileInfo->RefCount);
1155 
1156                 if(RelatedFileInfo && (TreeLength>1)) {
1157                     // it was an internal Open operation. Thus, assume
1158                     // RelatedFileInfo's Fcb to be valid
1159                     RelatedFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1160                     RelatedFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID;
1161                 }
1162                 // check path fragment size
1163                 if(CurName.Length > UDF_X_NAME_LEN * sizeof(WCHAR)) {
1164                     AdPrint(("    Path component is too long\n"));
1165                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1166                 }
1167                 // ...and now release previously acquired objects,
1168                 if(Res1) UDFReleaseResource(Res1);
1169                 if(Res2) {
1170                     UDFReleaseResource(Res2);
1171                     Res2 = NULL;
1172                 }
1173                 // acquire new _parent_ directory & try to open what
1174                 // we want.
1175 
1176                 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB);
1177                 UDFAcquireResourceExclusive(Res1 = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
1178 
1179                 // check traverse rights
1180                 RC = UDFCheckAccessRights(NULL, NULL, RelatedFileInfo->Fcb, PtrRelatedCCB, FILE_TRAVERSE, 0);
1181                 if(!NT_SUCCESS(RC)) {
1182                     NewFileInfo = NULL;
1183                     AdPrint(("    Traverse check failed\n"));
1184                     goto Skip_open_attempt;
1185                 }
1186                 // check if we should open normal File/Dir or SDir
1187                 if(CurName.Buffer[0] != ':') {
1188                     // standard open, nothing interesting....
1189                     RC = UDFOpenFile__(Vcb,
1190                                        IgnoreCase,TRUE,&CurName,
1191                                        RelatedFileInfo,&NewFileInfo,NULL);
1192                     if(RC == STATUS_FILE_DELETED) {
1193                         // file has gone, but system still remembers it...
1194                         NewFileInfo = NULL;
1195                         AdPrint(("    File deleted\n"));
1196                         RC = STATUS_ACCESS_DENIED;
1197 #ifdef UDF_DBG
1198                     } else
1199                     if(RC == STATUS_NOT_A_DIRECTORY) {
1200                         AdPrint(("    Not a directory\n"));
1201 #endif // UDF_DBG
1202                     } else
1203                     if(RC == STATUS_SHARING_PAUSED) {
1204                         AdPrint(("    Dloc is being initialized\n"));
1205                         BrutePoint();
1206                         RC = STATUS_SHARING_VIOLATION;
1207                     }
1208                 } else {
1209                     // And here we should open Stream Dir (if any, of cource)
1210                     RC = UDFOpenStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1211                     if(NT_SUCCESS(RC)) {
1212 SuccessOpen_SDir:
1213                         // this indicates that we needn't Stream Dir creation
1214                         StreamExists = TRUE;
1215                         StreamName.Buffer++;
1216                         StreamName.Length-=sizeof(WCHAR);
1217                         // update TailName
1218                         TailName = StreamName;
1219                     } else
1220                     if(RC == STATUS_NOT_FOUND) {
1221 #ifndef UDF_READ_ONLY_BUILD
1222                         // Stream Dir doesn't exist, but caller wants it to be
1223                         // created. Lets try to help him...
1224                         if((RequestedDisposition == FILE_CREATE) ||
1225                            (RequestedDisposition == FILE_OPEN_IF) ||
1226                            (RequestedDisposition == FILE_OVERWRITE_IF) ||
1227                             OpenTargetDirectory ) {
1228                             RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1229                             if(NT_SUCCESS(RC))
1230                                 goto SuccessOpen_SDir;
1231                         }
1232 #endif //UDF_READ_ONLY_BUILD
1233                     }
1234 /*                } else {
1235                     AdPrint(("    File deleted (2)\n"));
1236                     RC = STATUS_ACCESS_DENIED;*/
1237                 }
1238 #if 0
1239                 CollectStatistics(Vcb, MetaDataReads);
1240 #endif
1241 
1242 Skip_open_attempt:
1243 
1244                 // check if we have successfully opened path component
1245                 if(NT_SUCCESS(RC)) {
1246                     // Yesss !!!
1247                     if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1248                         // It is a first open operation
1249                         // Allocate new FCB
1250                         // Here we set FileObject pointer to NULL to avoid
1251                         // new CCB allocation
1252                         RC = UDFFirstOpenFile(Vcb,
1253                                        NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1254                                        &LocalPath, &CurName);
1255 
1256                         if(!NT_SUCCESS(RC)) {
1257                             BrutePoint();
1258                             AdPrint(("    Can't perform FirstOpen\n"));
1259                             UDFCloseFile__(Vcb, NewFileInfo);
1260                             if(PtrNewFcb) UDFCleanUpFCB(PtrNewFcb);
1261                             PtrNewFcb = NULL;
1262                             NewFileInfo->Fcb = NULL;
1263                             if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1264                                 MyFreePool__(NewFileInfo);
1265                                 NewFileInfo = NULL;
1266                             }
1267                             try_return(RC);
1268                         }
1269                     } else {
1270                         // It is not a first open operation
1271                         // Validate Fcb. It is possible to get
1272                         // not completly initialized Fcb here.
1273                         if(!(PtrNewFcb->FCBFlags & UDF_FCB_VALID)) {
1274                             BrutePoint();
1275                             AdPrint(("    Fcb not valid\n"));
1276                             UDFCloseFile__(Vcb, NewFileInfo);
1277                             PtrNewFcb = NULL;
1278                             if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1279                                 MyFreePool__(NewFileInfo);
1280                                 NewFileInfo = NULL;
1281                             }
1282                             try_return(RC = STATUS_ACCESS_DENIED);
1283                         }
1284                     }
1285                     // Acquire newly opened File...
1286                     Res2 = Res1;
1287                     UDF_CHECK_PAGING_IO_RESOURCE(NewFileInfo->Fcb->NTRequiredFCB);
1288                     UDFAcquireResourceExclusive(Res1 = &(NewFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
1289                     // ...and reference it
1290                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1291                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1292 
1293                     ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1294                     // update unwind information
1295                     LastGoodFileInfo = NewFileInfo;
1296                     LastGoodName = CurName;
1297                     TreeLength++;
1298                     // update current path
1299                     if(!StreamOpen ||
1300                          ((CurName.Buffer[0] != L':') &&
1301                           (!LocalPath.Length || (LocalPath.Buffer[LocalPath.Length/sizeof(WCHAR)-1] != L':'))) ) {
1302                         // we should not insert '\' before or after ':'
1303                         ASSERT(!LocalPath.Length ||
1304                                (LocalPath.Buffer[LocalPath.Length/2-1] != L'\\'));
1305                         RC = MyAppendUnicodeToString(&LocalPath, L"\\");
1306                         if(!NT_SUCCESS(RC)) try_return(RC);
1307                     }
1308                     RC = MyAppendUnicodeStringToStringTag(&LocalPath, &CurName, MEM_USLOC_TAG);
1309                     if(!NT_SUCCESS(RC))
1310                         try_return(RC);
1311 //                    DbgPrint("UDF: Open/Create File %ws : ReferenceCount %x\n",CurName.Buffer,PtrNewFcb->ReferenceCount);
1312                 } else {
1313                     AdPrint(("    Can't open file\n"));
1314                     // We have failed durring last Open attempt
1315                     // Roll back to last good state
1316                     PtrUDFNTRequiredFCB NtReqFcb = NULL;
1317                     // Cleanup FileInfo if any
1318                     if(NewFileInfo) {
1319                         PtrNewFcb = NewFileInfo->Fcb;
1320                         // acquire appropriate resource if possible
1321                         if(PtrNewFcb &&
1322                            PtrNewFcb->NTRequiredFCB) {
1323                             NtReqFcb = PtrNewFcb->NTRequiredFCB;
1324                             Res2 = Res1;
1325                             UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
1326                             UDFAcquireResourceExclusive(Res1 = &(NtReqFcb->MainResource),TRUE);
1327                         }
1328                         // cleanup pointer to Fcb in FileInfo to allow
1329                         // UDF_INFO package release FileInfo if there are
1330                         // no more references
1331                         if(PtrNewFcb &&
1332                            !PtrNewFcb->ReferenceCount &&
1333                            !PtrNewFcb->OpenHandleCount) {
1334                             NewFileInfo->Fcb = NULL;
1335                         }
1336                         // cleanup pointer to CommonFcb in Dloc to allow
1337                         // UDF_INFO package release Dloc if there are
1338                         // no more references
1339                         if(NewFileInfo->Dloc &&
1340                            !NewFileInfo->Dloc->LinkRefCount &&
1341                            (!PtrNewFcb || !PtrNewFcb->ReferenceCount)) {
1342                             NewFileInfo->Dloc->CommonFcb = NULL;
1343                         }
1344                         // try to release FileInfo
1345                         if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1346                             ASSERT(!PtrNewFcb);
1347                             if(PtrNewFcb) {
1348                                 BrutePoint();
1349                                 UDFCleanUpFCB(PtrNewFcb);
1350                             }
1351                             MyFreePool__(NewFileInfo);
1352                         } else {
1353                             // if we can't release FileInfo
1354                             // restore pointers to Fcb & CommonFcb in
1355                             // FileInfo & Dloc
1356                             NewFileInfo->Fcb = PtrNewFcb;
1357                             if(NtReqFcb)
1358                                 NewFileInfo->Dloc->CommonFcb = NtReqFcb;
1359                         }
1360                         // forget about last FileInfo & Fcb,
1361                         // further unwind staff needs only last good
1362                         // structures
1363                         PtrNewFcb = NULL;
1364                         NewFileInfo = NULL;
1365                     }
1366                 }
1367 
1368                 // should return error if 'delete in progress'
1369                 if(LastGoodFileInfo->Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE |
1370                                                       UDF_FCB_DELETED |
1371                                                       UDF_FCB_POSTED_RENAME)) {
1372                     AdPrint(("  Return DeletePending (no err)\n"));
1373                     try_return(RC = STATUS_DELETE_PENDING);
1374                 }
1375                 // update last good state information...
1376                 OldRelatedFileInfo = RelatedFileInfo;
1377                 RelatedFileInfo = NewFileInfo;
1378                 // ...and go to the next open cycle
1379             } else {
1380                 // ************
1381                 if(StreamOpen && (RC == STATUS_NOT_FOUND))
1382                     // handle SDir return code
1383                     RC = STATUS_OBJECT_NAME_NOT_FOUND;
1384                 if(RC == STATUS_OBJECT_NAME_NOT_FOUND) {
1385                     // good path, but no such file.... Amen
1386                     // break open loop and continue with Create
1387                     break;
1388                 }
1389                 if (!NT_SUCCESS(RC)) {
1390                     // Hard error or damaged data structures ...
1391 #ifdef UDF_DBG
1392                     if((RC != STATUS_OBJECT_PATH_NOT_FOUND) &&
1393                        (RC != STATUS_ACCESS_DENIED) &&
1394                        (RC != STATUS_NOT_A_DIRECTORY)) {
1395                         AdPrint(("    Hard error or damaged data structures\n"));
1396                     }
1397 #endif // UDF_DBG
1398                     // ... and exit with error
1399                     try_return(RC);
1400                 }
1401                 // discard changes for last successfully opened file
1402                 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount));
1403                 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1404                 RC = STATUS_SUCCESS;
1405                 ASSERT(!OpenTargetDirectory);
1406                 // break open loop and continue with Open
1407                 // (Create will be skipped)
1408                 break;
1409             }
1410         } // end of while(TRUE)
1411 
1412         // ****************
1413         // If "open target directory" was specified
1414         // ****************
1415         if(OpenTargetDirectory) {
1416 
1417             if(!UDFIsADirectory(LastGoodFileInfo)) {
1418                 AdPrint(("    Not a directory (2)\n"));
1419                 RC = STATUS_NOT_A_DIRECTORY;
1420             }
1421             if(!NT_SUCCESS(RC) ||
1422                TailName.Length) {
1423                 AdPrint(("    Target name should not contain (back)slashes\n"));
1424                 NewFileInfo = NULL;
1425                 try_return(RC = STATUS_OBJECT_NAME_INVALID);
1426             }
1427 
1428             NewFileInfo = LastGoodFileInfo;
1429             RtlCopyUnicodeString(&(PtrNewFileObject->FileName), &CurName);
1430 
1431             // now we have to check if last component exists...
1432             if(NT_SUCCESS(RC = UDFFindFile__(Vcb, IgnoreCase,
1433                                              &CurName, RelatedFileInfo))) {
1434                 // file exists, set this information in the Information field
1435                 ReturnedInformation = FILE_EXISTS;
1436                 AdPrint(("  Open Target: FILE_EXISTS\n"));
1437             } else
1438             if(RC == STATUS_OBJECT_NAME_NOT_FOUND) {
1439 #ifdef UDF_DBG
1440                 // check name. If there are '\\'s in TailName, some
1441                 // directories in path specified do not exist
1442                 for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) {
1443                     if((*TmpBuffer) == L'\\') {
1444                         ASSERT(FALSE);
1445                         AdPrint(("    Target name should not contain (back)slashes\n"));
1446                         try_return(RC = STATUS_OBJECT_NAME_INVALID);
1447                     }
1448                 }
1449 #endif // UDF_DBG
1450                 // Tell the I/O Manager that file does not exit
1451                 ReturnedInformation = FILE_DOES_NOT_EXIST;
1452                 AdPrint(("  Open Target: FILE_DOES_NOT_EXIST\n"));
1453                 RC = STATUS_SUCCESS; // is already set here
1454             } else {
1455                 AdPrint(("  Open Target: unexpected error\n"));
1456                 NewFileInfo = NULL;
1457                 ReturnedInformation = FILE_DOES_NOT_EXIST;
1458                 try_return(RC = STATUS_OBJECT_NAME_INVALID);
1459             }
1460 
1461 //          RC = STATUS_SUCCESS; // is already set here
1462 
1463             // Update the file object FsContext and FsContext2 fields
1464             //  to reflect the fact that the parent directory of the
1465             //  target has been opened
1466             PtrNewFcb = NewFileInfo->Fcb;
1467             UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount));
1468             UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1469             RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
1470             ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1471             if (!NT_SUCCESS(RC)) {
1472                 AdPrint(("    Can't perform OpenFile operation for target\n"));
1473                 try_return(RC);
1474             }
1475             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1476 
1477             ASSERT(Res1);
1478             RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1479             if(!NT_SUCCESS(RC)) {
1480                 AdPrint(("    Access/Share access check failed (Open Target)\n"));
1481             }
1482 
1483             try_return(RC);
1484         }
1485 
1486         // ****************
1487         // should we CREATE a new file ?
1488         // ****************
1489         if (!NT_SUCCESS(RC)) {
1490             if (RC == STATUS_OBJECT_NAME_NOT_FOUND ||
1491                 RC == STATUS_OBJECT_PATH_NOT_FOUND) {
1492                 if( ((RequestedDisposition == FILE_OPEN) ||
1493                     (RequestedDisposition == FILE_OVERWRITE)) /*&&
1494                     (!StreamOpen || !StreamExists)*/ ){
1495                     ReturnedInformation = FILE_DOES_NOT_EXIST;
1496                     AdPrint(("    File doesn't exist\n"));
1497                     try_return(RC);
1498                 }
1499             } else {
1500                 //  Any other operation return STATUS_ACCESS_DENIED.
1501                 AdPrint(("    Can't create due to unexpected error\n"));
1502                 try_return(RC);
1503             }
1504             // Object was not found, create if requested
1505             if ((RequestedDisposition != FILE_CREATE) && (RequestedDisposition != FILE_OPEN_IF) &&
1506                  (RequestedDisposition != FILE_OVERWRITE_IF) && (RequestedDisposition != FILE_SUPERSEDE)) {
1507                 AdPrint(("    File doesn't exist (2)\n"));
1508                 ReturnedInformation = FILE_DOES_NOT_EXIST;
1509                 try_return(RC);
1510             }
1511             // Check Volume ReadOnly attr
1512 #ifndef UDF_READ_ONLY_BUILD
1513             if((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)) {
1514 #endif //UDF_READ_ONLY_BUILD
1515                 ReturnedInformation = 0;
1516                 AdPrint(("    Write protected\n"));
1517                 try_return(RC = STATUS_MEDIA_WRITE_PROTECTED);
1518 #ifndef UDF_READ_ONLY_BUILD
1519             }
1520             // Check r/o + delete on close
1521             if(DeleteOnCloseSpecified &&
1522                (FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1523                 AdPrint(("    Can't create r/o file marked for deletion\n"));
1524                 try_return(RC = STATUS_CANNOT_DELETE);
1525             }
1526 
1527             // Create a new file/directory here ...
1528             if(StreamOpen)
1529                 StreamName.Buffer[StreamName.Length/sizeof(WCHAR)] = 0;
1530             for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) {
1531                 if((*TmpBuffer) == L'\\') {
1532                     AdPrint(("    Target name should not contain (back)slashes\n"));
1533                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1534                 }
1535             }
1536             if(  DirectoryOnlyRequested &&
1537                ((IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY) ||
1538                  StreamOpen || FALSE)) {
1539                 AdPrint(("    Creation of _temporary_ directory not permited\n"));
1540                 try_return(RC = STATUS_INVALID_PARAMETER);
1541             }
1542             // check access rights
1543             ASSERT(Res1);
1544             RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, DirectoryOnlyRequested ? FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, 0);
1545             if(!NT_SUCCESS(RC)) {
1546                 AdPrint(("    Creation of File/Dir not permitted\n"));
1547                 try_return(RC);
1548             }
1549             // Note that a FCB structure will be allocated at this time
1550             // and so will a CCB structure. Assume that these are called
1551             // PtrNewFcb and PtrNewCcb respectively.
1552             // Further, note that since the file is being created, no other
1553             // thread can have the file stream open at this time.
1554             RelatedFileInfo = OldRelatedFileInfo;
1555 
1556             RC = UDFCreateFile__(Vcb, IgnoreCase, &LastGoodTail, 0, 0,
1557                      Vcb->UseExtendedFE || (StreamOpen && !StreamExists),
1558                      (RequestedDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo);
1559             if(!NT_SUCCESS(RC)) {
1560                 AdPrint(("    Creation error\n"));
1561 Creation_Err_1:
1562                 if(NewFileInfo) {
1563                     PtrNewFcb = NewFileInfo->Fcb;
1564                     ASSERT(!PtrNewFcb);
1565                     if(PtrNewFcb &&
1566                        !PtrNewFcb->ReferenceCount &&
1567                        !PtrNewFcb->OpenHandleCount) {
1568                         NewFileInfo->Fcb = NULL;
1569                     }
1570                     if(NewFileInfo->Dloc &&
1571                        !NewFileInfo->Dloc->LinkRefCount) {
1572                         NewFileInfo->Dloc->CommonFcb = NULL;
1573                     }
1574                     if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1575                         if(PtrNewFcb) {
1576                             BrutePoint();
1577                             UDFCleanUpFCB(PtrNewFcb);
1578                         }
1579                         MyFreePool__(NewFileInfo);
1580                         PtrNewFcb = PtrNewFcb;
1581                     } else {
1582                         NewFileInfo->Fcb = PtrNewFcb;
1583                     }
1584                     PtrNewFcb = NULL;
1585                 }
1586                 try_return(RC);
1587             }
1588             // Update parent object
1589             if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) &&
1590                PtrRelatedFCB &&
1591                PtrRelatedFileObject &&
1592                (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
1593                 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED);
1594             }
1595 #if 0
1596             CollectStatistics(Vcb, MetaDataWrites);
1597 #endif
1598 
1599             if(DirectoryOnlyRequested) {
1600                 // user wants the directory to be created
1601                 RC = UDFRecordDirectory__(Vcb, NewFileInfo);
1602                 if(!NT_SUCCESS(RC)) {
1603                 AdPrint(("    Can't transform to directory\n"));
1604 Undo_Create_1:
1605                     if((RC != STATUS_FILE_IS_A_DIRECTORY) &&
1606                        (RC != STATUS_NOT_A_DIRECTORY) &&
1607                        (RC != STATUS_ACCESS_DENIED)) {
1608                         UDFFlushFile__(Vcb, NewFileInfo);
1609                         UDFUnlinkFile__(Vcb, NewFileInfo, TRUE);
1610                     }
1611                     UDFCloseFile__(Vcb, NewFileInfo);
1612                     BrutePoint();
1613                     goto Creation_Err_1;
1614                 }
1615 #if 0
1616                 CollectStatistics(Vcb, MetaDataWrites);
1617 #endif
1618             } else if(AllocationSize) {
1619                 // set initial file size
1620 /*                if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) {
1621                     AdPrint(("    Can't set initial file size\n"));
1622                     goto Undo_Create_1;
1623                 }
1624                 CollectStatistics(Vcb, MetaDataWrites);*/
1625             }
1626 
1627             if(StreamOpen && !StreamExists) {
1628 
1629                 // PHASE 0
1630 
1631                 // Open the newly created object (file)
1632                 if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1633                     // It is a first open operation
1634                     // Allocate new FCB
1635                     // Here we set FileObject pointer to NULL to avoid
1636                     // new CCB allocation
1637                     RC = UDFFirstOpenFile(Vcb,
1638                                    NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1639                                    &LocalPath, &LastGoodTail);
1640                     if(!NT_SUCCESS(RC)) {
1641                         AdPrint(("    Can't perform FirstOpenFile operation for file to contain stream\n"));
1642                         BrutePoint();
1643                         UDFCleanUpFCB(NewFileInfo->Fcb);
1644                         NewFileInfo->Fcb = NULL;
1645                         goto Creation_Err_1;
1646                     }
1647                 } else {
1648                     BrutePoint();
1649                 }
1650 
1651                 // Update unwind information
1652                 TreeLength++;
1653                 LastGoodFileInfo = NewFileInfo;
1654                 // update FCB tree
1655                 RC = MyAppendUnicodeToString(&LocalPath, L"\\");
1656                 if(!NT_SUCCESS(RC)) try_return(RC);
1657                 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &LastGoodTail, MEM_USLOC_TAG);
1658                 if(!NT_SUCCESS(RC))
1659                     goto Creation_Err_1;
1660                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1661                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1662                 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1663                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1664                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
1665 
1666                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1667                                            UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
1668                                            FILE_ACTION_ADDED);
1669 
1670                 // PHASE 1
1671 
1672                 // we need to create Stream Dir
1673                 RelatedFileInfo = NewFileInfo;
1674                 RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1675                 if(!NT_SUCCESS(RC)) {
1676                     AdPrint(("    Can't create SDir\n"));
1677                     BrutePoint();
1678                     goto Creation_Err_1;
1679                 }
1680 #if 0
1681                 CollectStatistics(Vcb, MetaDataWrites);
1682 #endif
1683 
1684                 // normalize stream name
1685                 StreamName.Buffer++;
1686                 StreamName.Length-=sizeof(WCHAR);
1687                 // Open the newly created object
1688                 if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1689                     // It is a first open operation
1690                     // Allocate new FCB
1691                     // Here we set FileObject pointer to NULL to avoid
1692                     // new CCB allocation
1693                     RC = UDFFirstOpenFile(Vcb,
1694                                    NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1695                                    &LocalPath, &(UDFGlobalData.UnicodeStrSDir));
1696                 } else {
1697                     BrutePoint();
1698                 }
1699                 if(!NT_SUCCESS(RC)) {
1700                     AdPrint(("    Can't perform OpenFile operation for SDir\n"));
1701                     BrutePoint();
1702                     goto Creation_Err_1;
1703                 }
1704 
1705                 // Update unwind information
1706                 TreeLength++;
1707                 LastGoodFileInfo = NewFileInfo;
1708                 // update FCB tree
1709                 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(UDFGlobalData.UnicodeStrSDir), MEM_USLOC_TAG);
1710                 if(!NT_SUCCESS(RC)) {
1711                     AdPrint(("    Can't append UNC str\n"));
1712                     BrutePoint();
1713                     goto Creation_Err_1;
1714                 }
1715                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1716                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1717                 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1718                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1719                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
1720 
1721                 // PHASE 2
1722 
1723                 // create stream
1724                 RelatedFileInfo = NewFileInfo;
1725                 RC = UDFCreateFile__(Vcb, IgnoreCase, &StreamName, 0, 0,
1726                          Vcb->UseExtendedFE, (RequestedDisposition == FILE_CREATE),
1727                          RelatedFileInfo, &NewFileInfo);
1728                 if(!NT_SUCCESS(RC)) {
1729                     AdPrint(("    Can't create Stream\n"));
1730                     BrutePoint();
1731                     goto Creation_Err_1;
1732                 }
1733 #if 0
1734                 CollectStatistics(Vcb, MetaDataWrites);
1735 #endif
1736 
1737                 // Update unwind information
1738                 LastGoodTail = StreamName;
1739             }
1740             // NT wants ARCHIVE bit to be set on Files
1741             if(!DirectoryOnlyRequested)
1742                 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
1743             // Open the newly created object
1744             if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1745                 // It is a first open operation
1746 #ifndef IFS_40
1747                 // Set attributes for the file ...
1748                 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index),
1749                                    NewFileInfo->Dloc->FileEntry, FileAttributes);
1750 #endif //IFS_40
1751                 // Allocate new FCB
1752                 // Here we set FileObject pointer to NULL to avoid
1753                 // new CCB allocation
1754                 RC = UDFFirstOpenFile(Vcb,
1755                                PtrNewFileObject, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1756                                &LocalPath, &LastGoodTail);
1757             } else {
1758                 BrutePoint();
1759             }
1760 
1761             if(!NT_SUCCESS(RC)) {
1762                 AdPrint(("    Can't perform OpenFile operation for file or stream\n"));
1763                 BrutePoint();
1764                 goto Undo_Create_1;
1765             }
1766 
1767             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.FileSize.QuadPart =
1768             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.ValidDataLength.QuadPart = 0;
1769             if(AllocationSize) {
1770                 // inform NT about size changes
1771                 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize.QuadPart = AllocationSize;
1772                 MmPrint(("    CcIsFileCached()\n"));
1773                 if(CcIsFileCached(PtrNewFileObject)) {
1774                      MmPrint(("    CcSetFileSizes()\n"));
1775                      BrutePoint();
1776                      CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize));
1777                      PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
1778                 }
1779             }
1780 
1781             // Update unwind information
1782             TreeLength++;
1783             LastGoodFileInfo = NewFileInfo;
1784 
1785             // Set the Share Access for the file stream.
1786             // The FCBShareAccess field will be set by the I/O Manager.
1787             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1788             RC = UDFSetAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1789 
1790             if(!NT_SUCCESS(RC)) {
1791                 AdPrint(("    Can't set Access Rights on Create\n"));
1792                 BrutePoint();
1793                 UDFFlushFile__(Vcb, NewFileInfo);
1794                 UDFUnlinkFile__(Vcb, NewFileInfo, TRUE);
1795                 try_return(RC);
1796             }
1797 
1798 #ifdef IFS_40
1799             // Set attributes for the file ...
1800             UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index),
1801                                NewFileInfo->Dloc->FileEntry, FileAttributes);
1802             // It is rather strange for me, but NT requires us to allow
1803             // Create operation for r/o + WriteAccess, but denies all
1804             // the rest operations in this case. Thus, we should update
1805             // r/o flag in Fcb _after_ Access check :-/
1806             if(FileAttributes & FILE_ATTRIBUTE_READONLY)
1807                 PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY;
1808 #endif //IFS_40
1809             // We call the notify package to report that the
1810             // we have added a stream.
1811             if(UDFIsAStream(NewFileInfo)) {
1812                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1813                                            FILE_NOTIFY_CHANGE_STREAM_NAME,
1814                                            FILE_ACTION_ADDED_STREAM );
1815             } else {
1816                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1817                                            UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
1818                                            FILE_ACTION_ADDED);
1819             }
1820 /*#ifdef UDF_DBG
1821             {
1822                 ULONG i;
1823                 PDIR_INDEX_HDR hDirIndex = NewFileInfo->ParentFile->Dloc->DirIndex;
1824 
1825                 for(i=0;DirIndex[i].FName.Buffer;i++) {
1826                     AdPrint(("%ws\n", DirIndex[i].FName.Buffer));
1827                 }
1828             }
1829 #endif*/
1830             ReturnedInformation = FILE_CREATED;
1831 
1832             try_return(RC);
1833 #endif //UDF_READ_ONLY_BUILD
1834 
1835         }
1836 
1837 AlreadyOpened:
1838 
1839         // ****************
1840         // we have always STATUS_SUCCESS here
1841         // ****************
1842 
1843         ASSERT(NewFileInfo != OldRelatedFileInfo);
1844         // A new CCB will be allocated.
1845         // Assume that this structure named PtrNewCcb
1846         RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
1847         if (!NT_SUCCESS(RC)) try_return(RC);
1848         PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1849 
1850         if(RequestedDisposition == FILE_CREATE) {
1851             ReturnedInformation = FILE_EXISTS;
1852             AdPrint(("    Object name collision\n"));
1853             try_return(RC = STATUS_OBJECT_NAME_COLLISION);
1854         }
1855 
1856         NtReqFcb = PtrNewFcb->NTRequiredFCB;
1857         NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(PtrNewFcb);
1858 
1859         // Check if caller wanted a directory only and target object
1860         //  is not a directory, or caller wanted a file only and target
1861         //  object is not a file ...
1862         if((PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) ||
1863               (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF) ||
1864               FileOnlyRequested)) {
1865             if(FileOnlyRequested) {
1866                 AdPrint(("    Can't open directory as a plain file\n"));
1867             } else {
1868                 AdPrint(("    Can't supersede directory\n"));
1869             }
1870             RC = STATUS_FILE_IS_A_DIRECTORY;
1871             try_return(RC);
1872         }
1873 
1874         if(DirectoryOnlyRequested && !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) {
1875             AdPrint(("    This is not a directory\n"));
1876             RC = STATUS_NOT_A_DIRECTORY;
1877             try_return(RC);
1878         }
1879 
1880         if(DeleteOnCloseSpecified && (PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY)) {
1881             AdPrint(("    Can't delete Read-Only file\n"));
1882             RC = STATUS_CANNOT_DELETE;
1883             try_return(RC);
1884         }
1885         // Check share access and fail if the share conflicts with an existing
1886         // open.
1887         ASSERT(Res1 != NULL);
1888         ASSERT(Res2 != NULL);
1889         RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1890         if(!NT_SUCCESS(RC)) {
1891             AdPrint(("    Access/Share access check failed\n"));
1892             try_return(RC);
1893         }
1894 
1895         RestoreShareAccess = TRUE;
1896 
1897         if(FileOnlyRequested) {
1898             //  If the user wants 'write access' access to the file make sure there
1899             //  is not a process mapping this file as an image.  Any attempt to
1900             //  delete the file will be stopped in fileinfo.cpp
1901             //
1902             //  If the user wants to delete on close, we must check at this
1903             //  point though.
1904             if( (DesiredAccess & FILE_WRITE_DATA) || DeleteOnCloseSpecified ) {
1905                 MmPrint(("    MmFlushImageSection();\n"));
1906                 NtReqFcb->AcqFlushCount++;
1907                 if(!MmFlushImageSection( &(NtReqFcb->SectionObject),
1908                                           MmFlushForWrite )) {
1909 
1910                     NtReqFcb->AcqFlushCount--;
1911                     RC = DeleteOnCloseSpecified ? STATUS_CANNOT_DELETE :
1912                                                   STATUS_SHARING_VIOLATION;
1913                     AdPrint(("    File is mapped or deletion in progress\n"));
1914                     try_return (RC);
1915                 }
1916                 NtReqFcb->AcqFlushCount--;
1917             }
1918             if(  NoBufferingSpecified &&
1919                 /*  (PtrNewFileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) &&*/
1920                !(PtrNewFcb->CachedOpenHandleCount) &&
1921                 (NtReqFcb->SectionObject.DataSectionObject) ) {
1922                 //  If this is a non-cached open, and there are no open cached
1923                 //  handles, but there is still a data section, attempt a flush
1924                 //  and purge operation to avoid cache coherency overhead later.
1925                 //  We ignore any I/O errors from the flush.
1926                 MmPrint(("    CcFlushCache()\n"));
1927                 CcFlushCache( &(NtReqFcb->SectionObject), NULL, 0, NULL );
1928                 MmPrint(("    CcPurgeCacheSection()\n"));
1929                 CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );
1930             }
1931         }
1932 
1933         if(DeleteOnCloseSpecified && UDFIsADirectory(NewFileInfo) && !UDFIsDirEmpty__(NewFileInfo)) {
1934             AdPrint(("    Directory in not empry\n"));
1935             try_return (RC = STATUS_DIRECTORY_NOT_EMPTY);
1936         }
1937 
1938         // Get attributes for the file ...
1939         TmpFileAttributes =
1940             (USHORT)UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
1941                                NewFileInfo->Dloc->FileEntry);
1942 
1943         if(DeleteOnCloseSpecified &&
1944            (TmpFileAttributes & FILE_ATTRIBUTE_READONLY)) {
1945             ASSERT(Res1 != NULL);
1946             ASSERT(Res2 != NULL);
1947             RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, FILE_DELETE_CHILD, 0);
1948             if(!NT_SUCCESS(RC)) {
1949                 AdPrint(("    Read-only. DeleteOnClose attempt failed\n"));
1950                 try_return (RC = STATUS_CANNOT_DELETE);
1951             }
1952         }
1953 
1954         // If a supersede or overwrite was requested, do so now ...
1955         if((RequestedDisposition == FILE_SUPERSEDE) ||
1956            (RequestedDisposition == FILE_OVERWRITE) ||
1957            (RequestedDisposition == FILE_OVERWRITE_IF)) {
1958             // Attempt the operation here ...
1959 
1960 #ifndef UDF_READ_ONLY_BUILD
1961             ASSERT(!UDFIsADirectory(NewFileInfo));
1962 
1963             if(RequestedDisposition == FILE_SUPERSEDE) {
1964                 BOOLEAN RestoreRO = FALSE;
1965 
1966                 ASSERT(Res1 != NULL);
1967                 ASSERT(Res2 != NULL);
1968                 // NT wants us to allow Supersede on RO files
1969                 if(PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY) {
1970                     // Imagine, that file is not RO and check other permissions
1971                     RestoreRO = TRUE;
1972                     PtrNewFcb->FCBFlags &= ~UDF_FCB_READ_ONLY;
1973                 }
1974                 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb, DELETE, 0);
1975                 if(RestoreRO) {
1976                     // Restore RO state if changed
1977                     PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY;
1978                 }
1979                 if(!NT_SUCCESS(RC)) {
1980                     AdPrint(("    Can't supersede. DELETE permission required\n"));
1981                     try_return (RC);
1982                 }
1983             } else {
1984                 ASSERT(Res1 != NULL);
1985                 ASSERT(Res2 != NULL);
1986                 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb,
1987                             FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES, 0);
1988                 if(!NT_SUCCESS(RC)) {
1989                     AdPrint(("    Can't overwrite. Permission denied\n"));
1990                     try_return (RC);
1991                 }
1992             }
1993             // Existing & requested System and Hidden bits must match
1994             if( (TmpFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) &
1995                 (FileAttributes ^ (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) ) {
1996                 AdPrint(("    The Hidden and/or System bits do not match\n"));
1997                 try_return(RC = STATUS_ACCESS_DENIED);
1998             }
1999 
2000             //  Before we actually truncate, check to see if the purge
2001             //  is going to fail.
2002             MmPrint(("    MmCanFileBeTruncated()\n"));
2003             if (!MmCanFileBeTruncated( &NtReqFcb->SectionObject,
2004                                        &(UDFGlobalData.UDFLargeZero) )) {
2005                 AdPrint(("    Can't truncate. File is mapped\n"));
2006                 try_return(RC = STATUS_USER_MAPPED_FILE);
2007             }
2008 
2009             ASSERT(Res1 != NULL);
2010             ASSERT(Res2 != NULL);
2011 
2012 #if 0
2013             CollectStatistics(Vcb, MetaDataWrites);
2014 #endif
2015             // Synchronize with PagingIo
2016             UDFAcquireResourceExclusive(PagingIoRes = &(NtReqFcb->PagingIoResource),TRUE);
2017             // Set file sizes
2018             if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, 0))) {
2019                 AdPrint(("    Error during resize operation\n"));
2020                 try_return(RC);
2021             }
2022 /*            if(AllocationSize) {
2023                 if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) {
2024                     AdPrint(("    Error during resize operation (2)\n"));
2025                     try_return(RC);
2026                 }
2027             }*/
2028             NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFSysGetAllocSize(Vcb, AllocationSize);
2029             NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
2030             NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = 0 /*AllocationSize*/;
2031             PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE;
2032             MmPrint(("    CcSetFileSizes()\n"));
2033             CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize));
2034             NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
2035             // Release PagingIoResource
2036             UDFReleaseResource(PagingIoRes);
2037             PagingIoRes = NULL;
2038 
2039             if(NT_SUCCESS(RC)) {
2040                 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
2041                 if (RequestedDisposition == FILE_SUPERSEDE) {
2042                     // Set attributes for the file ...
2043                     UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
2044                                        NewFileInfo->Dloc->FileEntry, FileAttributes);
2045                     ReturnedInformation = FILE_SUPERSEDED;
2046                 } else {
2047                     // Get attributes for the file ...
2048                     FileAttributes |= TmpFileAttributes;
2049                     // Set attributes for the file ...
2050                     UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
2051                                        NewFileInfo->Dloc->FileEntry, FileAttributes);
2052                     ReturnedInformation = FILE_OVERWRITTEN;
2053                 }
2054             }
2055             // notify changes
2056             UDFNotifyFullReportChange( Vcb, NewFileInfo,
2057                                        FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
2058                                        FILE_ACTION_MODIFIED);
2059 
2060             // Update parent object
2061             if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) &&
2062                PtrRelatedFCB &&
2063                PtrRelatedFileObject &&
2064                (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
2065                 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED);
2066             }
2067 #else //UDF_READ_ONLY_BUILD
2068             try_return(RC = STATUS_ACCESS_DENIED);
2069 #endif //UDF_READ_ONLY_BUILD
2070         } else {
2071             ReturnedInformation = FILE_OPENED;
2072         }
2073 
2074         // Update parent object
2075         if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_READ) &&
2076            PtrRelatedFCB &&
2077            PtrRelatedFileObject &&
2078            (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
2079             PtrRelatedFileObject->Flags |= FO_FILE_FAST_IO_READ;
2080         }
2081 
2082 try_exit:   NOTHING;
2083 
2084     } _SEH2_FINALLY {
2085         // Complete the request unless we are here as part of unwinding
2086         //  when an exception condition was encountered, OR
2087         //  if the request has been deferred (i.e. posted for later handling)
2088 
2089         if(RestoreVCBOpenCounter) {
2090             UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
2091             RestoreVCBOpenCounter = FALSE;
2092         }
2093 
2094         if (RC != STATUS_PENDING) {
2095             // If any intermediate (directory) open operations were performed,
2096             //  implement the corresponding close (do *not* however close
2097             //  the target we have opened on behalf of the caller ...).
2098 
2099 #if 0
2100             if(NT_SUCCESS(RC)) {
2101                 CollectStatistics2(Vcb, SuccessfulCreates);
2102             } else {
2103                 CollectStatistics2(Vcb, FailedCreates);
2104             }
2105 #endif
2106 
2107             if (NT_SUCCESS(RC) && PtrNewFcb) {
2108                 // Update the file object such that:
2109                 //  (a) the FsContext field points to the NTRequiredFCB field
2110                 //       in the FCB
2111                 //  (b) the FsContext2 field points to the CCB created as a
2112                 //       result of the open operation
2113 
2114                 // If write-through was requested, then mark the file object
2115                 //  appropriately
2116 
2117                 // directories are not cached
2118                 // so we should prevent flush attepmts on cleanup
2119                 if(!(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) {
2120 #ifndef UDF_READ_ONLY_BUILD
2121                     if(WriteThroughRequested) {
2122                         PtrNewFileObject->Flags |= FO_WRITE_THROUGH;
2123                         PtrNewFcb->FCBFlags |= UDF_FCB_WRITE_THROUGH;
2124                         MmPrint(("        FO_WRITE_THROUGH\n"));
2125                     }
2126 #endif //UDF_READ_ONLY_BUILD
2127                     if(SequentialIoRequested &&
2128                        !(Vcb->CompatFlags & UDF_VCB_IC_IGNORE_SEQUENTIAL_IO)) {
2129                         PtrNewFileObject->Flags |= FO_SEQUENTIAL_ONLY;
2130                         MmPrint(("        FO_SEQUENTIAL_ONLY\n"));
2131 #ifndef UDF_READ_ONLY_BUILD
2132                         if(Vcb->TargetDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
2133                             PtrNewFileObject->Flags &= ~FO_WRITE_THROUGH;
2134                             PtrNewFcb->FCBFlags &= ~UDF_FCB_WRITE_THROUGH;
2135                             MmPrint(("        FILE_REMOVABLE_MEDIA + FO_SEQUENTIAL_ONLY => ~FO_WRITE_THROUGH\n"));
2136                         }
2137 #endif //UDF_READ_ONLY_BUILD
2138                         if(PtrNewFcb->FileInfo) {
2139                             UDFSetFileAllocMode__(PtrNewFcb->FileInfo, EXTENT_FLAG_ALLOC_SEQUENTIAL);
2140                         }
2141                     }
2142                     if(NoBufferingSpecified) {
2143                         PtrNewFileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
2144                         MmPrint(("        FO_NO_INTERMEDIATE_BUFFERING\n"));
2145                     } else {
2146                         PtrNewFileObject->Flags |= FO_CACHE_SUPPORTED;
2147                         MmPrint(("        FO_CACHE_SUPPORTED\n"));
2148                     }
2149                 }
2150 
2151                 if((DesiredAccess & FILE_EXECUTE) /*&&
2152                    !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)*/) {
2153                     MmPrint(("        FO_FILE_FAST_IO_READ\n"));
2154                     PtrNewFileObject->Flags |= FO_FILE_FAST_IO_READ;
2155                 }
2156                 // All right. Now we can safely increment OpenHandleCount
2157                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBHandleCount));
2158                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->OpenHandleCount));
2159 
2160                 if(PtrNewFileObject->Flags & FO_CACHE_SUPPORTED)
2161                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->CachedOpenHandleCount));
2162                 // Store some flags in CCB
2163                 if(PtrNewCcb) {
2164                     PtrNewCcb->TreeLength = TreeLength;
2165                     // delete on close
2166 #ifndef UDF_READ_ONLY_BUILD
2167                     if(DeleteOnCloseSpecified) {
2168                         ASSERT(!(PtrNewFcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
2169                         PtrNewCcb->CCBFlags |= UDF_CCB_DELETE_ON_CLOSE;
2170                     }
2171 #endif //UDF_READ_ONLY_BUILD
2172                     // case sensetivity
2173                     if(!IgnoreCase) {
2174                         // remember this for possible Rename/Move operation
2175                         PtrNewCcb->CCBFlags |= UDF_CCB_CASE_SENSETIVE;
2176                         PtrNewFileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
2177                     }
2178                     if(IsFileObjectReadOnly(PtrNewFileObject)) {
2179                         UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCountRO));
2180                         PtrNewCcb->CCBFlags |= UDF_CCB_READ_ONLY;
2181                     }
2182                 } else {
2183                     BrutePoint();
2184                 }
2185                 // it was a stream...
2186                 if(StreamOpen)
2187                     PtrNewFileObject->Flags |= FO_STREAM_FILE;
2188 //                PtrNewCcb->CCBFlags |= UDF_CCB_VALID;
2189                 // increment the number of outstanding open operations on this
2190                 // logical volume (i.e. volume cannot be dismounted)
2191                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
2192                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
2193                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
2194 #ifdef UDF_DBG
2195                 // We have no FileInfo for Volume
2196                 if(PtrNewFcb->FileInfo) {
2197                     ASSERT_REF(PtrNewFcb->ReferenceCount >= PtrNewFcb->FileInfo->RefCount);
2198                 }
2199 #endif // UDF_DBG
2200                 AdPrint(("    FCB %x, CCB %x, FO %x, Flags %x\n", PtrNewFcb, PtrNewCcb, PtrNewFileObject, PtrNewFcb->FCBFlags));
2201 
2202                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2203 
2204             } else if(!NT_SUCCESS(RC)) {
2205                 // Perform failure related post-processing now
2206                 if(RestoreShareAccess && NtReqFcb && PtrNewFileObject) {
2207                     IoRemoveShareAccess(PtrNewFileObject, &(NtReqFcb->FCBShareAccess));
2208                 }
2209                 UDFCleanUpCCB(PtrNewCcb);
2210                 if(PtrNewFileObject) {
2211                     PtrNewFileObject->FsContext2 = NULL;
2212                 }
2213                 // We have successfully opened LastGoodFileInfo,
2214                 // so mark it as VALID to avoid future troubles...
2215                 if(LastGoodFileInfo && LastGoodFileInfo->Fcb) {
2216                     LastGoodFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID;
2217                     if(LastGoodFileInfo->Fcb->NTRequiredFCB) {
2218                         LastGoodFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
2219                     }
2220                 }
2221                 // Release resources...
2222                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2223                 ASSERT(AcquiredVcb);
2224                 // close the chain
2225                 UDFCloseFileInfoChain(Vcb, LastGoodFileInfo, TreeLength, TRUE);
2226                 // cleanup FCBs (if any)
2227                 if(  Vcb && (PtrNewFcb != Vcb->RootDirFCB) &&
2228                      LastGoodFileInfo ) {
2229                     UDFCleanUpFcbChain(Vcb, LastGoodFileInfo, TreeLength, TRUE);
2230                 } else {
2231                     ASSERT(!LastGoodFileInfo);
2232                 }
2233             } else {
2234                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2235             }
2236             // As long as this unwinding is not being performed as a result of
2237             //  an exception condition, complete the IRP ...
2238             if (!_SEH2_AbnormalTermination()) {
2239                 Irp->IoStatus.Status = RC;
2240                 Irp->IoStatus.Information = ReturnedInformation;
2241 
2242                 // complete the IRP
2243                 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
2244                 // Free up the Irp Context
2245                 UDFReleaseIrpContext(PtrIrpContext);
2246             }
2247         } else {
2248             UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2249         }
2250 
2251         if(AcquiredVcb) {
2252             UDFReleaseResource(&(Vcb->VCBResource));
2253         }
2254         // free allocated tmp buffers (if any)
2255         if(AbsolutePathName.Buffer)
2256             MyFreePool__(AbsolutePathName.Buffer);
2257         if(LocalPath.Buffer)
2258             MyFreePool__(LocalPath.Buffer);
2259         if(TailNameBuffer)
2260             MyFreePool__(TailNameBuffer);
2261     } _SEH2_END;
2262 
2263     return(RC);
2264 } // end UDFCommonCreate()
2265 
2266 /*************************************************************************
2267 *
2268 * Function: UDFFirstOpenFile()
2269 *
2270 * Description:
2271 *   Perform first Open/Create initialization.
2272 *
2273 * Expected Interrupt Level (for execution) :
2274 *
2275 *  IRQL_PASSIVE_LEVEL
2276 *
2277 * Return Value: STATUS_SUCCESS/Error
2278 *
2279 *************************************************************************/
2280 NTSTATUS
2281 UDFFirstOpenFile(
2282     IN PVCB                    Vcb,                // volume control block
2283     IN PFILE_OBJECT            PtrNewFileObject,   // I/O Mgr. created file object
2284    OUT PtrUDFFCB*              PtrNewFcb,
2285     IN PUDF_FILE_INFO          RelatedFileInfo,
2286     IN PUDF_FILE_INFO          NewFileInfo,
2287     IN PUNICODE_STRING         LocalPath,
2288     IN PUNICODE_STRING         CurName
2289     )
2290 {
2291 //    DIR_INDEX           NewFileIndex;
2292     PtrUDFObjectName    NewFCBName;
2293     PtrUDFNTRequiredFCB NtReqFcb;
2294     NTSTATUS            RC;
2295     BOOLEAN             Linked = TRUE;
2296     PDIR_INDEX_HDR      hDirIndex;
2297     PDIR_INDEX_ITEM     DirIndex;
2298 
2299     AdPrint(("UDFFirstOpenFile\n"));
2300 
2301     if(!((*PtrNewFcb) = UDFAllocateFCB())) {
2302         AdPrint(("Can't allocate FCB\n"));
2303         return STATUS_INSUFFICIENT_RESOURCES;
2304     }
2305 
2306     // Allocate and set new FCB unique name (equal to absolute path name)
2307     if(!(NewFCBName = UDFAllocateObjectName())) return STATUS_INSUFFICIENT_RESOURCES;
2308 
2309     if(RelatedFileInfo && RelatedFileInfo->Fcb &&
2310        !(RelatedFileInfo->Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY)) {
2311         RC = MyCloneUnicodeString(&(NewFCBName->ObjectName), &(RelatedFileInfo->Fcb->FCBName->ObjectName));
2312     } else {
2313         RC = MyInitUnicodeString(&(NewFCBName->ObjectName), L"");
2314     }
2315     if(!NT_SUCCESS(RC))
2316         return STATUS_INSUFFICIENT_RESOURCES;
2317     if( (CurName->Buffer[0] != L':') &&
2318         (!LocalPath->Length ||
2319             ((LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L':') /*&&
2320              (LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L'\\')*/) )) {
2321         RC = MyAppendUnicodeToString(&(NewFCBName->ObjectName), L"\\");
2322         if(!NT_SUCCESS(RC)) {
2323             UDFReleaseObjectName(NewFCBName);
2324             return STATUS_INSUFFICIENT_RESOURCES;
2325         }
2326     }
2327 
2328     // Make link between Fcb and FileInfo
2329     (*PtrNewFcb)->FileInfo = NewFileInfo;
2330     NewFileInfo->Fcb = (*PtrNewFcb);
2331     (*PtrNewFcb)->ParentFcb = RelatedFileInfo->Fcb;
2332 
2333     if(!((*PtrNewFcb)->NTRequiredFCB = NewFileInfo->Dloc->CommonFcb)) {
2334         (*PtrNewFcb)->NTRequiredFCB = (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
2335         if(!((*PtrNewFcb)->NTRequiredFCB)) {
2336             UDFReleaseObjectName(NewFCBName);
2337             return STATUS_INSUFFICIENT_RESOURCES;
2338         }
2339 
2340         UDFPrint(("UDFAllocateNtReqFCB: %x\n", (*PtrNewFcb)->NTRequiredFCB));
2341         RtlZeroMemory((*PtrNewFcb)->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
2342         (*PtrNewFcb)->FileInfo->Dloc->CommonFcb = (*PtrNewFcb)->NTRequiredFCB;
2343         Linked = FALSE;
2344     } else {
2345         if(!(NewFileInfo->Dloc->CommonFcb->NtReqFCBFlags & UDF_NTREQ_FCB_VALID)) {
2346             (*PtrNewFcb)->NTRequiredFCB = NULL;
2347             BrutePoint();
2348             UDFReleaseObjectName(NewFCBName);
2349             return STATUS_ACCESS_DENIED;
2350         }
2351     }
2352 
2353     NtReqFcb = (*PtrNewFcb)->NTRequiredFCB;
2354     // Set times
2355     if(!Linked) {
2356         UDFGetFileXTime((*PtrNewFcb)->FileInfo,
2357             &(NtReqFcb->CreationTime.QuadPart),
2358             &(NtReqFcb->LastAccessTime.QuadPart),
2359             &(NtReqFcb->ChangeTime.QuadPart),
2360             &(NtReqFcb->LastWriteTime.QuadPart) );
2361 
2362         // Set the allocation size for the object is specified
2363         NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart =
2364             UDFSysGetAllocSize(Vcb, NewFileInfo->Dloc->DataLoc.Length);
2365 //        NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, NewFileInfo);
2366         NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
2367         NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = NewFileInfo->Dloc->DataLoc.Length;
2368     }
2369     // begin transaction
2370     UDFAcquireResourceExclusive(&(Vcb->FcbListResource), TRUE);
2371 
2372     RC = UDFInitializeFCB(*PtrNewFcb, Vcb, NewFCBName,
2373                  UDFIsADirectory(NewFileInfo) ? UDF_FCB_DIRECTORY : 0, PtrNewFileObject);
2374     if(!NT_SUCCESS(RC)) {
2375         if(!Linked) {
2376             MyFreePool__((*PtrNewFcb)->NTRequiredFCB);
2377             (*PtrNewFcb)->NTRequiredFCB = NULL;
2378         }
2379         UDFReleaseResource(&(Vcb->FcbListResource));
2380         return RC;
2381     }
2382     // set Read-only attribute
2383     if(!UDFIsAStreamDir(NewFileInfo)) {
2384         hDirIndex = UDFGetDirIndexByFileInfo(NewFileInfo);
2385 #ifdef UDF_DBG
2386         if(!hDirIndex) {
2387             BrutePoint();
2388         } else {
2389 #endif // UDF_DBG
2390             if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, NewFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) {
2391                 (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY;
2392             }
2393             MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), &(DirIndex->FName), MEM_USOBJ_TAG);
2394 #ifdef UDF_DBG
2395         }
2396 #endif // UDF_DBG
2397     } else if (RelatedFileInfo->ParentFile) {
2398         hDirIndex = UDFGetDirIndexByFileInfo(RelatedFileInfo);
2399         if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, RelatedFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) {
2400             (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY;
2401         }
2402         RC = MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), CurName, MEM_USOBJ_TAG);
2403 //    } else {
2404 //        BrutePoint();
2405     }
2406     // do not allocate CCB if it is internal Create/Open
2407     if(NT_SUCCESS(RC)) {
2408         if(PtrNewFileObject) {
2409             RC = UDFOpenFile(Vcb, PtrNewFileObject, *PtrNewFcb);
2410         } else {
2411             RC = STATUS_SUCCESS;
2412         }
2413     }
2414     UDFReleaseResource(&(Vcb->FcbListResource));
2415     // end transaction
2416 
2417 //    if(!NT_SUCCESS(RC)) return RC;
2418 
2419     return RC;
2420 } // end UDFFirstOpenFile()
2421 
2422 /*************************************************************************
2423 *
2424 * Function: UDFOpenFile()
2425 *
2426 * Description:
2427 *   Open a file/dir for the caller.
2428 *
2429 * Expected Interrupt Level (for execution) :
2430 *
2431 *  IRQL_PASSIVE_LEVEL
2432 *
2433 * Return Value: STATUS_SUCCESS/Error
2434 *
2435 *************************************************************************/
2436 NTSTATUS
2437 UDFOpenFile(
2438     PVCB                 Vcb,                // volume control block
2439     PFILE_OBJECT         PtrNewFileObject,   // I/O Mgr. created file object
2440     PtrUDFFCB            PtrNewFcb
2441     )
2442 {
2443     NTSTATUS                RC = STATUS_SUCCESS;
2444     PtrUDFCCB               Ccb = NULL;
2445     PtrUDFNTRequiredFCB     NtReqFcb;
2446 
2447     AdPrint(("UDFOpenFile\n"));
2448     ASSERT((PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB)
2449          ||(PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB));
2450 
2451     _SEH2_TRY {
2452 
2453 #if 0
2454         CollectStatistics2(Vcb, CreateHits);
2455 #endif
2456         // create a new CCB structure
2457         if (!(Ccb = UDFAllocateCCB())) {
2458             AdPrint(("Can't allocate CCB\n"));
2459             PtrNewFileObject->FsContext2 = NULL;
2460             //
2461             UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
2462             UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
2463             RC = STATUS_INSUFFICIENT_RESOURCES;
2464             try_return(RC);
2465         }
2466         // initialize the CCB
2467         Ccb->Fcb = PtrNewFcb;
2468         // initialize the CCB to point to the file object
2469         Ccb->FileObject = PtrNewFileObject;
2470 
2471         // initialize the file object appropriately
2472         PtrNewFileObject->FsContext2 = (PVOID)(Ccb);
2473         PtrNewFileObject->Vpb = Vcb->Vpb;
2474         PtrNewFileObject->FsContext = (PVOID)(NtReqFcb = PtrNewFcb->NTRequiredFCB);
2475         PtrNewFileObject->SectionObjectPointer = &(NtReqFcb->SectionObject);
2476 #ifdef DBG
2477 //        NtReqFcb ->FileObject = PtrNewFileObject;
2478 #endif //DBG
2479 
2480 #ifdef UDF_DELAYED_CLOSE
2481         PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE;
2482 #endif //UDF_DELAYED_CLOSE
2483 
2484         UDFAcquireResourceExclusive(&(PtrNewFcb->CcbListResource),TRUE);
2485         // insert CCB into linked list of open file object to Fcb or
2486         // to Vcb and do other intialization
2487         InsertTailList(&(PtrNewFcb->NextCCB), &(Ccb->NextCCB));
2488         UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
2489         UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
2490         UDFReleaseResource(&(PtrNewFcb->CcbListResource));
2491 
2492 try_exit:   NOTHING;
2493     } _SEH2_FINALLY {
2494         NOTHING;
2495     } _SEH2_END;
2496 
2497     return(RC);
2498 } // end UDFOpenFile()
2499 
2500 
2501 /*************************************************************************
2502 *
2503 * Function: UDFInitializeFCB()
2504 *
2505 * Description:
2506 *   Initialize a new FCB structure and also the sent-in file object
2507 *   (if supplied)
2508 *
2509 * Expected Interrupt Level (for execution) :
2510 *
2511 *  IRQL_PASSIVE_LEVEL
2512 *
2513 * Return Value: None
2514 *
2515 *************************************************************************/
2516 NTSTATUS
2517 UDFInitializeFCB(
2518     IN PtrUDFFCB        PtrNewFcb,      // FCB structure to be initialized
2519     IN PVCB             Vcb,            // logical volume (VCB) pointer
2520     IN PtrUDFObjectName PtrObjectName,  // name of the object
2521     IN ULONG            Flags,          // is this a file/directory, etc.
2522     IN PFILE_OBJECT     FileObject)     // optional file object to be initialized
2523 {
2524     AdPrint(("UDFInitializeFCB\n"));
2525     NTSTATUS status;
2526     BOOLEAN Linked = TRUE;
2527 
2528     if(!PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource) {
2529         // record signature
2530         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode = UDF_NODE_TYPE_NT_REQ_FCB;
2531         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeByteSize = sizeof(UDFNTRequiredFCB);
2532         // Initialize the ERESOURCE objects
2533         if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->MainResource)))) {
2534             AdPrint(("    Can't init resource\n"));
2535             return status;
2536         }
2537         if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->PagingIoResource)))) {
2538             AdPrint(("    Can't init resource (2)\n"));
2539             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource));
2540             return status;
2541         }
2542         // Fill NT required Fcb part
2543         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource = &(PtrNewFcb->NTRequiredFCB->MainResource);
2544         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = &(PtrNewFcb->NTRequiredFCB->PagingIoResource);
2545         // Itialize byte-range locks support structure
2546         FsRtlInitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock),NULL,NULL);
2547         // Init reference counter
2548         PtrNewFcb->NTRequiredFCB->CommonRefCount = 0;
2549         Linked = FALSE;
2550     } else {
2551         ASSERT(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode == UDF_NODE_TYPE_NT_REQ_FCB);
2552     }
2553     if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->CcbListResource)))) {
2554         AdPrint(("    Can't init resource (3)\n"));
2555         BrutePoint();
2556         if(!Linked) {
2557             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->PagingIoResource));
2558             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource));
2559             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource =
2560             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = NULL;
2561             FsRtlUninitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock));
2562         }
2563         return status;
2564     }
2565 
2566     // caller MUST ensure that VCB has been acquired exclusively
2567     InsertTailList(&(Vcb->NextFCB), &(PtrNewFcb->NextFCB));
2568 
2569     // initialize the various list heads
2570     InitializeListHead(&(PtrNewFcb->NextCCB));
2571 
2572     PtrNewFcb->ReferenceCount = 0;
2573     PtrNewFcb->OpenHandleCount = 0;
2574 
2575     PtrNewFcb->FCBFlags = Flags | UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE;
2576 
2577     PtrNewFcb->FCBName = PtrObjectName;
2578 
2579     PtrNewFcb->Vcb = Vcb;
2580 
2581     return STATUS_SUCCESS;
2582 } // end UDFInitializeFCB()
2583 
2584