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