xref: /reactos/drivers/filesystems/udfs/create.cpp (revision 76dd2fcf)
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_PTR)(TailName.Buffer) - (ULONG_PTR)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                     ReturnedInformation = FILE_DOES_NOT_EXIST;
1147                     try_return(RC);
1148                 }
1149 
1150                 ASSERT_REF(RelatedFileInfo->Fcb->ReferenceCount >= RelatedFileInfo->RefCount);
1151 
1152                 if(RelatedFileInfo && (TreeLength>1)) {
1153                     // it was an internal Open operation. Thus, assume
1154                     // RelatedFileInfo's Fcb to be valid
1155                     RelatedFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1156                     RelatedFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID;
1157                 }
1158                 // check path fragment size
1159                 if(CurName.Length > UDF_X_NAME_LEN * sizeof(WCHAR)) {
1160                     AdPrint(("    Path component is too long\n"));
1161                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1162                 }
1163                 // ...and now release previously acquired objects,
1164                 if(Res1) UDFReleaseResource(Res1);
1165                 if(Res2) {
1166                     UDFReleaseResource(Res2);
1167                     Res2 = NULL;
1168                 }
1169                 // acquire new _parent_ directory & try to open what
1170                 // we want.
1171 
1172                 UDF_CHECK_PAGING_IO_RESOURCE(RelatedFileInfo->Fcb->NTRequiredFCB);
1173                 UDFAcquireResourceExclusive(Res1 = &(RelatedFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
1174 
1175                 // check traverse rights
1176                 RC = UDFCheckAccessRights(NULL, NULL, RelatedFileInfo->Fcb, PtrRelatedCCB, FILE_TRAVERSE, 0);
1177                 if(!NT_SUCCESS(RC)) {
1178                     NewFileInfo = NULL;
1179                     AdPrint(("    Traverse check failed\n"));
1180                     goto Skip_open_attempt;
1181                 }
1182                 // check if we should open normal File/Dir or SDir
1183                 if(CurName.Buffer[0] != ':') {
1184                     // standard open, nothing interesting....
1185                     RC = UDFOpenFile__(Vcb,
1186                                        IgnoreCase,TRUE,&CurName,
1187                                        RelatedFileInfo,&NewFileInfo,NULL);
1188                     if(RC == STATUS_FILE_DELETED) {
1189                         // file has gone, but system still remembers it...
1190                         NewFileInfo = NULL;
1191                         AdPrint(("    File deleted\n"));
1192                         RC = STATUS_ACCESS_DENIED;
1193 #ifdef UDF_DBG
1194                     } else
1195                     if(RC == STATUS_NOT_A_DIRECTORY) {
1196                         AdPrint(("    Not a directory\n"));
1197 #endif // UDF_DBG
1198                     } else
1199                     if(RC == STATUS_SHARING_PAUSED) {
1200                         AdPrint(("    Dloc is being initialized\n"));
1201                         BrutePoint();
1202                         RC = STATUS_SHARING_VIOLATION;
1203                     }
1204                 } else {
1205                     // And here we should open Stream Dir (if any, of cource)
1206                     RC = UDFOpenStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1207                     if(NT_SUCCESS(RC)) {
1208 SuccessOpen_SDir:
1209                         // this indicates that we needn't Stream Dir creation
1210                         StreamExists = TRUE;
1211                         StreamName.Buffer++;
1212                         StreamName.Length-=sizeof(WCHAR);
1213                         // update TailName
1214                         TailName = StreamName;
1215                     } else
1216                     if(RC == STATUS_NOT_FOUND) {
1217 #ifndef UDF_READ_ONLY_BUILD
1218                         // Stream Dir doesn't exist, but caller wants it to be
1219                         // created. Lets try to help him...
1220                         if((RequestedDisposition == FILE_CREATE) ||
1221                            (RequestedDisposition == FILE_OPEN_IF) ||
1222                            (RequestedDisposition == FILE_OVERWRITE_IF) ||
1223                             OpenTargetDirectory ) {
1224                             RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1225                             if(NT_SUCCESS(RC))
1226                                 goto SuccessOpen_SDir;
1227                         }
1228 #endif //UDF_READ_ONLY_BUILD
1229                     }
1230 /*                } else {
1231                     AdPrint(("    File deleted (2)\n"));
1232                     RC = STATUS_ACCESS_DENIED;*/
1233                 }
1234 #if 0
1235                 CollectStatistics(Vcb, MetaDataReads);
1236 #endif
1237 
1238 Skip_open_attempt:
1239 
1240                 // check if we have successfully opened path component
1241                 if(NT_SUCCESS(RC)) {
1242                     // Yesss !!!
1243                     if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1244                         // It is a first open operation
1245                         // Allocate new FCB
1246                         // Here we set FileObject pointer to NULL to avoid
1247                         // new CCB allocation
1248                         RC = UDFFirstOpenFile(Vcb,
1249                                        NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1250                                        &LocalPath, &CurName);
1251 
1252                         if(!NT_SUCCESS(RC)) {
1253                             BrutePoint();
1254                             AdPrint(("    Can't perform FirstOpen\n"));
1255                             UDFCloseFile__(Vcb, NewFileInfo);
1256                             if(PtrNewFcb) UDFCleanUpFCB(PtrNewFcb);
1257                             PtrNewFcb = NULL;
1258                             NewFileInfo->Fcb = NULL;
1259                             if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1260                                 MyFreePool__(NewFileInfo);
1261                                 NewFileInfo = NULL;
1262                             }
1263                             try_return(RC);
1264                         }
1265                     } else {
1266                         // It is not a first open operation
1267                         // Validate Fcb. It is possible to get
1268                         // not completly initialized Fcb here.
1269                         if(!(PtrNewFcb->FCBFlags & UDF_FCB_VALID)) {
1270                             BrutePoint();
1271                             AdPrint(("    Fcb not valid\n"));
1272                             UDFCloseFile__(Vcb, NewFileInfo);
1273                             PtrNewFcb = NULL;
1274                             if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1275                                 MyFreePool__(NewFileInfo);
1276                                 NewFileInfo = NULL;
1277                             }
1278                             try_return(RC = STATUS_ACCESS_DENIED);
1279                         }
1280                     }
1281                     // Acquire newly opened File...
1282                     Res2 = Res1;
1283                     UDF_CHECK_PAGING_IO_RESOURCE(NewFileInfo->Fcb->NTRequiredFCB);
1284                     UDFAcquireResourceExclusive(Res1 = &(NewFileInfo->Fcb->NTRequiredFCB->MainResource),TRUE);
1285                     // ...and reference it
1286                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1287                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1288 
1289                     ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1290                     // update unwind information
1291                     LastGoodFileInfo = NewFileInfo;
1292                     LastGoodName = CurName;
1293                     TreeLength++;
1294                     // update current path
1295                     if(!StreamOpen ||
1296                          ((CurName.Buffer[0] != L':') &&
1297                           (!LocalPath.Length || (LocalPath.Buffer[LocalPath.Length/sizeof(WCHAR)-1] != L':'))) ) {
1298                         // we should not insert '\' before or after ':'
1299                         ASSERT(!LocalPath.Length ||
1300                                (LocalPath.Buffer[LocalPath.Length/2-1] != L'\\'));
1301                         RC = MyAppendUnicodeToString(&LocalPath, L"\\");
1302                         if(!NT_SUCCESS(RC)) try_return(RC);
1303                     }
1304                     RC = MyAppendUnicodeStringToStringTag(&LocalPath, &CurName, MEM_USLOC_TAG);
1305                     if(!NT_SUCCESS(RC))
1306                         try_return(RC);
1307 //                    DbgPrint("UDF: Open/Create File %ws : ReferenceCount %x\n",CurName.Buffer,PtrNewFcb->ReferenceCount);
1308                 } else {
1309                     AdPrint(("    Can't open file\n"));
1310                     // We have failed durring last Open attempt
1311                     // Roll back to last good state
1312                     PtrUDFNTRequiredFCB NtReqFcb = NULL;
1313                     // Cleanup FileInfo if any
1314                     if(NewFileInfo) {
1315                         PtrNewFcb = NewFileInfo->Fcb;
1316                         // acquire appropriate resource if possible
1317                         if(PtrNewFcb &&
1318                            PtrNewFcb->NTRequiredFCB) {
1319                             NtReqFcb = PtrNewFcb->NTRequiredFCB;
1320                             Res2 = Res1;
1321                             UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
1322                             UDFAcquireResourceExclusive(Res1 = &(NtReqFcb->MainResource),TRUE);
1323                         }
1324                         // cleanup pointer to Fcb in FileInfo to allow
1325                         // UDF_INFO package release FileInfo if there are
1326                         // no more references
1327                         if(PtrNewFcb &&
1328                            !PtrNewFcb->ReferenceCount &&
1329                            !PtrNewFcb->OpenHandleCount) {
1330                             NewFileInfo->Fcb = NULL;
1331                         }
1332                         // cleanup pointer to CommonFcb in Dloc to allow
1333                         // UDF_INFO package release Dloc if there are
1334                         // no more references
1335                         if(NewFileInfo->Dloc &&
1336                            !NewFileInfo->Dloc->LinkRefCount &&
1337                            (!PtrNewFcb || !PtrNewFcb->ReferenceCount)) {
1338                             NewFileInfo->Dloc->CommonFcb = NULL;
1339                         }
1340                         // try to release FileInfo
1341                         if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1342                             ASSERT(!PtrNewFcb);
1343                             if(PtrNewFcb) {
1344                                 BrutePoint();
1345                                 UDFCleanUpFCB(PtrNewFcb);
1346                             }
1347                             MyFreePool__(NewFileInfo);
1348                         } else {
1349                             // if we can't release FileInfo
1350                             // restore pointers to Fcb & CommonFcb in
1351                             // FileInfo & Dloc
1352                             NewFileInfo->Fcb = PtrNewFcb;
1353                             if(NtReqFcb)
1354                                 NewFileInfo->Dloc->CommonFcb = NtReqFcb;
1355                         }
1356                         // forget about last FileInfo & Fcb,
1357                         // further unwind staff needs only last good
1358                         // structures
1359                         PtrNewFcb = NULL;
1360                         NewFileInfo = NULL;
1361                     }
1362                 }
1363 
1364                 // should return error if 'delete in progress'
1365                 if(LastGoodFileInfo->Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE |
1366                                                       UDF_FCB_DELETED |
1367                                                       UDF_FCB_POSTED_RENAME)) {
1368                     AdPrint(("  Return DeletePending (no err)\n"));
1369                     try_return(RC = STATUS_DELETE_PENDING);
1370                 }
1371                 // update last good state information...
1372                 OldRelatedFileInfo = RelatedFileInfo;
1373                 RelatedFileInfo = NewFileInfo;
1374                 // ...and go to the next open cycle
1375             } else {
1376                 // ************
1377                 if(StreamOpen && (RC == STATUS_NOT_FOUND))
1378                     // handle SDir return code
1379                     RC = STATUS_OBJECT_NAME_NOT_FOUND;
1380                 if(RC == STATUS_OBJECT_NAME_NOT_FOUND) {
1381                     // good path, but no such file.... Amen
1382                     // break open loop and continue with Create
1383                     break;
1384                 }
1385                 if (!NT_SUCCESS(RC)) {
1386                     // Hard error or damaged data structures ...
1387 #ifdef UDF_DBG
1388                     if((RC != STATUS_OBJECT_PATH_NOT_FOUND) &&
1389                        (RC != STATUS_ACCESS_DENIED) &&
1390                        (RC != STATUS_NOT_A_DIRECTORY)) {
1391                         AdPrint(("    Hard error or damaged data structures\n"));
1392                     }
1393 #endif // UDF_DBG
1394                     // ... and exit with error
1395                     try_return(RC);
1396                 }
1397                 // discard changes for last successfully opened file
1398                 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount));
1399                 UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1400                 RC = STATUS_SUCCESS;
1401                 ASSERT(!OpenTargetDirectory);
1402                 // break open loop and continue with Open
1403                 // (Create will be skipped)
1404                 break;
1405             }
1406         } // end of while(TRUE)
1407 
1408         // ****************
1409         // If "open target directory" was specified
1410         // ****************
1411         if(OpenTargetDirectory) {
1412 
1413             if(!UDFIsADirectory(LastGoodFileInfo)) {
1414                 AdPrint(("    Not a directory (2)\n"));
1415                 RC = STATUS_NOT_A_DIRECTORY;
1416             }
1417             if(!NT_SUCCESS(RC) ||
1418                TailName.Length) {
1419                 AdPrint(("    Target name should not contain (back)slashes\n"));
1420                 NewFileInfo = NULL;
1421                 try_return(RC = STATUS_OBJECT_NAME_INVALID);
1422             }
1423 
1424             NewFileInfo = LastGoodFileInfo;
1425             RtlCopyUnicodeString(&(PtrNewFileObject->FileName), &CurName);
1426 
1427             // now we have to check if last component exists...
1428             if(NT_SUCCESS(RC = UDFFindFile__(Vcb, IgnoreCase,
1429                                              &CurName, RelatedFileInfo))) {
1430                 // file exists, set this information in the Information field
1431                 ReturnedInformation = FILE_EXISTS;
1432                 AdPrint(("  Open Target: FILE_EXISTS\n"));
1433             } else
1434             if(RC == STATUS_OBJECT_NAME_NOT_FOUND) {
1435 #ifdef UDF_DBG
1436                 // check name. If there are '\\'s in TailName, some
1437                 // directories in path specified do not exist
1438                 for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) {
1439                     if((*TmpBuffer) == L'\\') {
1440                         ASSERT(FALSE);
1441                         AdPrint(("    Target name should not contain (back)slashes\n"));
1442                         try_return(RC = STATUS_OBJECT_NAME_INVALID);
1443                     }
1444                 }
1445 #endif // UDF_DBG
1446                 // Tell the I/O Manager that file does not exit
1447                 ReturnedInformation = FILE_DOES_NOT_EXIST;
1448                 AdPrint(("  Open Target: FILE_DOES_NOT_EXIST\n"));
1449                 RC = STATUS_SUCCESS; // is already set here
1450             } else {
1451                 AdPrint(("  Open Target: unexpected error\n"));
1452                 NewFileInfo = NULL;
1453                 try_return(RC = STATUS_OBJECT_NAME_INVALID);
1454             }
1455 
1456 //          RC = STATUS_SUCCESS; // is already set here
1457 
1458             // Update the file object FsContext and FsContext2 fields
1459             //  to reflect the fact that the parent directory of the
1460             //  target has been opened
1461             PtrNewFcb = NewFileInfo->Fcb;
1462             UDFInterlockedDecrement((PLONG)&(PtrNewFcb->ReferenceCount));
1463             UDFInterlockedDecrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1464             RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
1465             ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1466             if (!NT_SUCCESS(RC)) {
1467                 AdPrint(("    Can't perform OpenFile operation for target\n"));
1468                 try_return(RC);
1469             }
1470             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1471 
1472             ASSERT(Res1);
1473             RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1474             if(!NT_SUCCESS(RC)) {
1475                 AdPrint(("    Access/Share access check failed (Open Target)\n"));
1476             }
1477 
1478             try_return(RC);
1479         }
1480 
1481         // ****************
1482         // should we CREATE a new file ?
1483         // ****************
1484         if (!NT_SUCCESS(RC)) {
1485             if (RC == STATUS_OBJECT_NAME_NOT_FOUND ||
1486                 RC == STATUS_OBJECT_PATH_NOT_FOUND) {
1487                 if( ((RequestedDisposition == FILE_OPEN) ||
1488                     (RequestedDisposition == FILE_OVERWRITE)) /*&&
1489                     (!StreamOpen || !StreamExists)*/ ){
1490                     ReturnedInformation = FILE_DOES_NOT_EXIST;
1491                     AdPrint(("    File doesn't exist\n"));
1492                     try_return(RC);
1493                 }
1494             } else {
1495                 //  Any other operation return STATUS_ACCESS_DENIED.
1496                 AdPrint(("    Can't create due to unexpected error\n"));
1497                 try_return(RC);
1498             }
1499             // Object was not found, create if requested
1500             if ((RequestedDisposition != FILE_CREATE) && (RequestedDisposition != FILE_OPEN_IF) &&
1501                  (RequestedDisposition != FILE_OVERWRITE_IF) && (RequestedDisposition != FILE_SUPERSEDE)) {
1502                 AdPrint(("    File doesn't exist (2)\n"));
1503                 try_return(RC);
1504             }
1505             // Check Volume ReadOnly attr
1506 #ifndef UDF_READ_ONLY_BUILD
1507             if((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)) {
1508 #endif //UDF_READ_ONLY_BUILD
1509                 ReturnedInformation = 0;
1510                 AdPrint(("    Write protected\n"));
1511                 try_return(RC = STATUS_MEDIA_WRITE_PROTECTED);
1512 #ifndef UDF_READ_ONLY_BUILD
1513             }
1514             // Check r/o + delete on close
1515             if(DeleteOnCloseSpecified &&
1516                (FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1517                 AdPrint(("    Can't create r/o file marked for deletion\n"));
1518                 try_return(RC = STATUS_CANNOT_DELETE);
1519             }
1520 
1521             // Create a new file/directory here ...
1522             if(StreamOpen)
1523                 StreamName.Buffer[StreamName.Length/sizeof(WCHAR)] = 0;
1524             for(TmpBuffer = LastGoodTail.Buffer; *TmpBuffer; TmpBuffer++) {
1525                 if((*TmpBuffer) == L'\\') {
1526                     AdPrint(("    Target name should not contain (back)slashes\n"));
1527                     try_return(RC = STATUS_OBJECT_NAME_INVALID);
1528                 }
1529             }
1530             if(  DirectoryOnlyRequested &&
1531                ((IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY) ||
1532                  StreamOpen || FALSE)) {
1533                 AdPrint(("    Creation of _temporary_ directory not permited\n"));
1534                 try_return(RC = STATUS_INVALID_PARAMETER);
1535             }
1536             // check access rights
1537             ASSERT(Res1);
1538             RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, DirectoryOnlyRequested ? FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE, 0);
1539             if(!NT_SUCCESS(RC)) {
1540                 AdPrint(("    Creation of File/Dir not permitted\n"));
1541                 try_return(RC);
1542             }
1543             // Note that a FCB structure will be allocated at this time
1544             // and so will a CCB structure. Assume that these are called
1545             // PtrNewFcb and PtrNewCcb respectively.
1546             // Further, note that since the file is being created, no other
1547             // thread can have the file stream open at this time.
1548             RelatedFileInfo = OldRelatedFileInfo;
1549 
1550             RC = UDFCreateFile__(Vcb, IgnoreCase, &LastGoodTail, 0, 0,
1551                      Vcb->UseExtendedFE || (StreamOpen && !StreamExists),
1552                      (RequestedDisposition == FILE_CREATE), RelatedFileInfo, &NewFileInfo);
1553             if(!NT_SUCCESS(RC)) {
1554                 AdPrint(("    Creation error\n"));
1555 Creation_Err_1:
1556                 if(NewFileInfo) {
1557                     PtrNewFcb = NewFileInfo->Fcb;
1558                     ASSERT(!PtrNewFcb);
1559                     if(PtrNewFcb &&
1560                        !PtrNewFcb->ReferenceCount &&
1561                        !PtrNewFcb->OpenHandleCount) {
1562                         NewFileInfo->Fcb = NULL;
1563                     }
1564                     if(NewFileInfo->Dloc &&
1565                        !NewFileInfo->Dloc->LinkRefCount) {
1566                         NewFileInfo->Dloc->CommonFcb = NULL;
1567                     }
1568                     if(UDFCleanUpFile__(Vcb, NewFileInfo)) {
1569                         if(PtrNewFcb) {
1570                             BrutePoint();
1571                             UDFCleanUpFCB(PtrNewFcb);
1572                         }
1573                         MyFreePool__(NewFileInfo);
1574                         PtrNewFcb = PtrNewFcb;
1575                     } else {
1576                         NewFileInfo->Fcb = PtrNewFcb;
1577                     }
1578                     PtrNewFcb = NULL;
1579                 }
1580                 try_return(RC);
1581             }
1582             // Update parent object
1583             if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) &&
1584                PtrRelatedFCB &&
1585                PtrRelatedFileObject &&
1586                (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
1587                 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED);
1588             }
1589 #if 0
1590             CollectStatistics(Vcb, MetaDataWrites);
1591 #endif
1592 
1593             if(DirectoryOnlyRequested) {
1594                 // user wants the directory to be created
1595                 RC = UDFRecordDirectory__(Vcb, NewFileInfo);
1596                 if(!NT_SUCCESS(RC)) {
1597                 AdPrint(("    Can't transform to directory\n"));
1598 Undo_Create_1:
1599                     if((RC != STATUS_FILE_IS_A_DIRECTORY) &&
1600                        (RC != STATUS_NOT_A_DIRECTORY) &&
1601                        (RC != STATUS_ACCESS_DENIED)) {
1602                         UDFFlushFile__(Vcb, NewFileInfo);
1603                         UDFUnlinkFile__(Vcb, NewFileInfo, TRUE);
1604                     }
1605                     UDFCloseFile__(Vcb, NewFileInfo);
1606                     BrutePoint();
1607                     goto Creation_Err_1;
1608                 }
1609 #if 0
1610                 CollectStatistics(Vcb, MetaDataWrites);
1611 #endif
1612             } else if(AllocationSize) {
1613                 // set initial file size
1614 /*                if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) {
1615                     AdPrint(("    Can't set initial file size\n"));
1616                     goto Undo_Create_1;
1617                 }
1618                 CollectStatistics(Vcb, MetaDataWrites);*/
1619             }
1620 
1621             if(StreamOpen && !StreamExists) {
1622 
1623                 // PHASE 0
1624 
1625                 // Open the newly created object (file)
1626                 if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1627                     // It is a first open operation
1628                     // Allocate new FCB
1629                     // Here we set FileObject pointer to NULL to avoid
1630                     // new CCB allocation
1631                     RC = UDFFirstOpenFile(Vcb,
1632                                    NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1633                                    &LocalPath, &LastGoodTail);
1634                     if(!NT_SUCCESS(RC)) {
1635                         AdPrint(("    Can't perform FirstOpenFile operation for file to contain stream\n"));
1636                         BrutePoint();
1637                         UDFCleanUpFCB(NewFileInfo->Fcb);
1638                         NewFileInfo->Fcb = NULL;
1639                         goto Creation_Err_1;
1640                     }
1641                 } else {
1642                     BrutePoint();
1643                 }
1644 
1645                 // Update unwind information
1646                 TreeLength++;
1647                 LastGoodFileInfo = NewFileInfo;
1648                 // update FCB tree
1649                 RC = MyAppendUnicodeToString(&LocalPath, L"\\");
1650                 if(!NT_SUCCESS(RC)) try_return(RC);
1651                 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &LastGoodTail, MEM_USLOC_TAG);
1652                 if(!NT_SUCCESS(RC))
1653                     goto Creation_Err_1;
1654                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1655                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1656                 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1657                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1658                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
1659 
1660                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1661                                            UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
1662                                            FILE_ACTION_ADDED);
1663 
1664                 // PHASE 1
1665 
1666                 // we need to create Stream Dir
1667                 RelatedFileInfo = NewFileInfo;
1668                 RC = UDFCreateStreamDir__(Vcb, RelatedFileInfo, &NewFileInfo);
1669                 if(!NT_SUCCESS(RC)) {
1670                     AdPrint(("    Can't create SDir\n"));
1671                     BrutePoint();
1672                     goto Creation_Err_1;
1673                 }
1674 #if 0
1675                 CollectStatistics(Vcb, MetaDataWrites);
1676 #endif
1677 
1678                 // normalize stream name
1679                 StreamName.Buffer++;
1680                 StreamName.Length-=sizeof(WCHAR);
1681                 // Open the newly created object
1682                 if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1683                     // It is a first open operation
1684                     // Allocate new FCB
1685                     // Here we set FileObject pointer to NULL to avoid
1686                     // new CCB allocation
1687                     RC = UDFFirstOpenFile(Vcb,
1688                                    NULL, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1689                                    &LocalPath, &(UDFGlobalData.UnicodeStrSDir));
1690                 } else {
1691                     BrutePoint();
1692                 }
1693                 if(!NT_SUCCESS(RC)) {
1694                     AdPrint(("    Can't perform OpenFile operation for SDir\n"));
1695                     BrutePoint();
1696                     goto Creation_Err_1;
1697                 }
1698 
1699                 // Update unwind information
1700                 TreeLength++;
1701                 LastGoodFileInfo = NewFileInfo;
1702                 // update FCB tree
1703                 RC = MyAppendUnicodeStringToStringTag(&LocalPath, &(UDFGlobalData.UnicodeStrSDir), MEM_USLOC_TAG);
1704                 if(!NT_SUCCESS(RC)) {
1705                     AdPrint(("    Can't append UNC str\n"));
1706                     BrutePoint();
1707                     goto Creation_Err_1;
1708                 }
1709                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
1710                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
1711                 ASSERT_REF(PtrNewFcb->ReferenceCount >= NewFileInfo->RefCount);
1712                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
1713                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
1714 
1715                 // PHASE 2
1716 
1717                 // create stream
1718                 RelatedFileInfo = NewFileInfo;
1719                 RC = UDFCreateFile__(Vcb, IgnoreCase, &StreamName, 0, 0,
1720                          Vcb->UseExtendedFE, (RequestedDisposition == FILE_CREATE),
1721                          RelatedFileInfo, &NewFileInfo);
1722                 if(!NT_SUCCESS(RC)) {
1723                     AdPrint(("    Can't create Stream\n"));
1724                     BrutePoint();
1725                     goto Creation_Err_1;
1726                 }
1727 #if 0
1728                 CollectStatistics(Vcb, MetaDataWrites);
1729 #endif
1730 
1731                 // Update unwind information
1732                 LastGoodTail = StreamName;
1733             }
1734             // NT wants ARCHIVE bit to be set on Files
1735             if(!DirectoryOnlyRequested)
1736                 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
1737             // Open the newly created object
1738             if (!(PtrNewFcb = NewFileInfo->Fcb)) {
1739                 // It is a first open operation
1740 #ifndef IFS_40
1741                 // Set attributes for the file ...
1742                 UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index),
1743                                    NewFileInfo->Dloc->FileEntry, FileAttributes);
1744 #endif //IFS_40
1745                 // Allocate new FCB
1746                 // Here we set FileObject pointer to NULL to avoid
1747                 // new CCB allocation
1748                 RC = UDFFirstOpenFile(Vcb,
1749                                PtrNewFileObject, &PtrNewFcb, RelatedFileInfo, NewFileInfo,
1750                                &LocalPath, &LastGoodTail);
1751             } else {
1752                 BrutePoint();
1753             }
1754 
1755             if(!NT_SUCCESS(RC)) {
1756                 AdPrint(("    Can't perform OpenFile operation for file or stream\n"));
1757                 BrutePoint();
1758                 goto Undo_Create_1;
1759             }
1760 
1761             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.FileSize.QuadPart =
1762             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.ValidDataLength.QuadPart = 0;
1763             if(AllocationSize) {
1764                 // inform NT about size changes
1765                 PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize.QuadPart = AllocationSize;
1766                 MmPrint(("    CcIsFileCached()\n"));
1767                 if(CcIsFileCached(PtrNewFileObject)) {
1768                      MmPrint(("    CcSetFileSizes()\n"));
1769                      BrutePoint();
1770                      CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.AllocationSize));
1771                      PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
1772                 }
1773             }
1774 
1775             // Update unwind information
1776             TreeLength++;
1777             LastGoodFileInfo = NewFileInfo;
1778 
1779             // Set the Share Access for the file stream.
1780             // The FCBShareAccess field will be set by the I/O Manager.
1781             PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1782             RC = UDFSetAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1783 
1784             if(!NT_SUCCESS(RC)) {
1785                 AdPrint(("    Can't set Access Rights on Create\n"));
1786                 BrutePoint();
1787                 UDFFlushFile__(Vcb, NewFileInfo);
1788                 UDFUnlinkFile__(Vcb, NewFileInfo, TRUE);
1789                 try_return(RC);
1790             }
1791 
1792 #ifdef IFS_40
1793             // Set attributes for the file ...
1794             UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo),NewFileInfo->Index),
1795                                NewFileInfo->Dloc->FileEntry, FileAttributes);
1796             // It is rather strange for me, but NT requires us to allow
1797             // Create operation for r/o + WriteAccess, but denies all
1798             // the rest operations in this case. Thus, we should update
1799             // r/o flag in Fcb _after_ Access check :-/
1800             if(FileAttributes & FILE_ATTRIBUTE_READONLY)
1801                 PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY;
1802 #endif //IFS_40
1803             // We call the notify package to report that the
1804             // we have added a stream.
1805             if(UDFIsAStream(NewFileInfo)) {
1806                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1807                                            FILE_NOTIFY_CHANGE_STREAM_NAME,
1808                                            FILE_ACTION_ADDED_STREAM );
1809             } else {
1810                 UDFNotifyFullReportChange( Vcb, NewFileInfo,
1811                                            UDFIsADirectory(NewFileInfo) ? FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
1812                                            FILE_ACTION_ADDED);
1813             }
1814 /*#ifdef UDF_DBG
1815             {
1816                 ULONG i;
1817                 PDIR_INDEX_HDR hDirIndex = NewFileInfo->ParentFile->Dloc->DirIndex;
1818 
1819                 for(i=0;DirIndex[i].FName.Buffer;i++) {
1820                     AdPrint(("%ws\n", DirIndex[i].FName.Buffer));
1821                 }
1822             }
1823 #endif*/
1824             ReturnedInformation = FILE_CREATED;
1825 
1826             try_return(RC);
1827 #endif //UDF_READ_ONLY_BUILD
1828 
1829         }
1830 
1831 AlreadyOpened:
1832 
1833         // ****************
1834         // we have always STATUS_SUCCESS here
1835         // ****************
1836 
1837         ASSERT(NewFileInfo != OldRelatedFileInfo);
1838         // A new CCB will be allocated.
1839         // Assume that this structure named PtrNewCcb
1840         RC = UDFOpenFile(Vcb, PtrNewFileObject, PtrNewFcb);
1841         if (!NT_SUCCESS(RC)) try_return(RC);
1842         PtrNewCcb = (PtrUDFCCB)(PtrNewFileObject->FsContext2);
1843 
1844         if(RequestedDisposition == FILE_CREATE) {
1845             ReturnedInformation = FILE_EXISTS;
1846             AdPrint(("    Object name collision\n"));
1847             try_return(RC = STATUS_OBJECT_NAME_COLLISION);
1848         }
1849 
1850         NtReqFcb = PtrNewFcb->NTRequiredFCB;
1851         NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(PtrNewFcb);
1852 
1853         // Check if caller wanted a directory only and target object
1854         //  is not a directory, or caller wanted a file only and target
1855         //  object is not a file ...
1856         if((PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY) && ((RequestedDisposition == FILE_SUPERSEDE) ||
1857               (RequestedDisposition == FILE_OVERWRITE) || (RequestedDisposition == FILE_OVERWRITE_IF) ||
1858               FileOnlyRequested)) {
1859             if(FileOnlyRequested) {
1860                 AdPrint(("    Can't open directory as a plain file\n"));
1861             } else {
1862                 AdPrint(("    Can't supersede directory\n"));
1863             }
1864             RC = STATUS_FILE_IS_A_DIRECTORY;
1865             try_return(RC);
1866         }
1867 
1868         if(DirectoryOnlyRequested && !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) {
1869             AdPrint(("    This is not a directory\n"));
1870             RC = STATUS_NOT_A_DIRECTORY;
1871             try_return(RC);
1872         }
1873 
1874         if(DeleteOnCloseSpecified && (PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY)) {
1875             AdPrint(("    Can't delete Read-Only file\n"));
1876             RC = STATUS_CANNOT_DELETE;
1877             try_return(RC);
1878         }
1879         // Check share access and fail if the share conflicts with an existing
1880         // open.
1881         ASSERT(Res1 != NULL);
1882         ASSERT(Res2 != NULL);
1883         RC = UDFCheckAccessRights(PtrNewFileObject, AccessState, PtrNewFcb, PtrNewCcb, DesiredAccess, ShareAccess);
1884         if(!NT_SUCCESS(RC)) {
1885             AdPrint(("    Access/Share access check failed\n"));
1886             try_return(RC);
1887         }
1888 
1889         RestoreShareAccess = TRUE;
1890 
1891         if(FileOnlyRequested) {
1892             //  If the user wants 'write access' access to the file make sure there
1893             //  is not a process mapping this file as an image.  Any attempt to
1894             //  delete the file will be stopped in fileinfo.cpp
1895             //
1896             //  If the user wants to delete on close, we must check at this
1897             //  point though.
1898             if( (DesiredAccess & FILE_WRITE_DATA) || DeleteOnCloseSpecified ) {
1899                 MmPrint(("    MmFlushImageSection();\n"));
1900                 NtReqFcb->AcqFlushCount++;
1901                 if(!MmFlushImageSection( &(NtReqFcb->SectionObject),
1902                                           MmFlushForWrite )) {
1903 
1904                     NtReqFcb->AcqFlushCount--;
1905                     RC = DeleteOnCloseSpecified ? STATUS_CANNOT_DELETE :
1906                                                   STATUS_SHARING_VIOLATION;
1907                     AdPrint(("    File is mapped or deletion in progress\n"));
1908                     try_return (RC);
1909                 }
1910                 NtReqFcb->AcqFlushCount--;
1911             }
1912             if(  NoBufferingSpecified &&
1913                 /*  (PtrNewFileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) &&*/
1914                !(PtrNewFcb->CachedOpenHandleCount) &&
1915                 (NtReqFcb->SectionObject.DataSectionObject) ) {
1916                 //  If this is a non-cached open, and there are no open cached
1917                 //  handles, but there is still a data section, attempt a flush
1918                 //  and purge operation to avoid cache coherency overhead later.
1919                 //  We ignore any I/O errors from the flush.
1920                 MmPrint(("    CcFlushCache()\n"));
1921                 CcFlushCache( &(NtReqFcb->SectionObject), NULL, 0, NULL );
1922                 MmPrint(("    CcPurgeCacheSection()\n"));
1923                 CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );
1924             }
1925         }
1926 
1927         if(DeleteOnCloseSpecified && UDFIsADirectory(NewFileInfo) && !UDFIsDirEmpty__(NewFileInfo)) {
1928             AdPrint(("    Directory in not empry\n"));
1929             try_return (RC = STATUS_DIRECTORY_NOT_EMPTY);
1930         }
1931 
1932         // Get attributes for the file ...
1933         TmpFileAttributes =
1934             (USHORT)UDFAttributesToNT(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
1935                                NewFileInfo->Dloc->FileEntry);
1936 
1937         if(DeleteOnCloseSpecified &&
1938            (TmpFileAttributes & FILE_ATTRIBUTE_READONLY)) {
1939             ASSERT(Res1 != NULL);
1940             ASSERT(Res2 != NULL);
1941             RC = UDFCheckAccessRights(NULL, NULL, OldRelatedFileInfo->Fcb, PtrRelatedCCB, FILE_DELETE_CHILD, 0);
1942             if(!NT_SUCCESS(RC)) {
1943                 AdPrint(("    Read-only. DeleteOnClose attempt failed\n"));
1944                 try_return (RC = STATUS_CANNOT_DELETE);
1945             }
1946         }
1947 
1948         // If a supersede or overwrite was requested, do so now ...
1949         if((RequestedDisposition == FILE_SUPERSEDE) ||
1950            (RequestedDisposition == FILE_OVERWRITE) ||
1951            (RequestedDisposition == FILE_OVERWRITE_IF)) {
1952             // Attempt the operation here ...
1953 
1954 #ifndef UDF_READ_ONLY_BUILD
1955             ASSERT(!UDFIsADirectory(NewFileInfo));
1956 
1957             if(RequestedDisposition == FILE_SUPERSEDE) {
1958                 BOOLEAN RestoreRO = FALSE;
1959 
1960                 ASSERT(Res1 != NULL);
1961                 ASSERT(Res2 != NULL);
1962                 // NT wants us to allow Supersede on RO files
1963                 if(PtrNewFcb->FCBFlags & UDF_FCB_READ_ONLY) {
1964                     // Imagine, that file is not RO and check other permissions
1965                     RestoreRO = TRUE;
1966                     PtrNewFcb->FCBFlags &= ~UDF_FCB_READ_ONLY;
1967                 }
1968                 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb, DELETE, 0);
1969                 if(RestoreRO) {
1970                     // Restore RO state if changed
1971                     PtrNewFcb->FCBFlags |= UDF_FCB_READ_ONLY;
1972                 }
1973                 if(!NT_SUCCESS(RC)) {
1974                     AdPrint(("    Can't supersede. DELETE permission required\n"));
1975                     try_return (RC);
1976                 }
1977             } else {
1978                 ASSERT(Res1 != NULL);
1979                 ASSERT(Res2 != NULL);
1980                 RC = UDFCheckAccessRights(NULL, NULL, PtrNewFcb, PtrNewCcb,
1981                             FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES, 0);
1982                 if(!NT_SUCCESS(RC)) {
1983                     AdPrint(("    Can't overwrite. Permission denied\n"));
1984                     try_return (RC);
1985                 }
1986             }
1987             // Existing & requested System and Hidden bits must match
1988             if( (TmpFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) &
1989                 (FileAttributes ^ (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) ) {
1990                 AdPrint(("    The Hidden and/or System bits do not match\n"));
1991                 try_return(RC = STATUS_ACCESS_DENIED);
1992             }
1993 
1994             //  Before we actually truncate, check to see if the purge
1995             //  is going to fail.
1996             MmPrint(("    MmCanFileBeTruncated()\n"));
1997             if (!MmCanFileBeTruncated( &NtReqFcb->SectionObject,
1998                                        &(UDFGlobalData.UDFLargeZero) )) {
1999                 AdPrint(("    Can't truncate. File is mapped\n"));
2000                 try_return(RC = STATUS_USER_MAPPED_FILE);
2001             }
2002 
2003             ASSERT(Res1 != NULL);
2004             ASSERT(Res2 != NULL);
2005 
2006 #if 0
2007             CollectStatistics(Vcb, MetaDataWrites);
2008 #endif
2009             // Synchronize with PagingIo
2010             UDFAcquireResourceExclusive(PagingIoRes = &(NtReqFcb->PagingIoResource),TRUE);
2011             // Set file sizes
2012             if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, 0))) {
2013                 AdPrint(("    Error during resize operation\n"));
2014                 try_return(RC);
2015             }
2016 /*            if(AllocationSize) {
2017                 if(!NT_SUCCESS(RC = UDFResizeFile__(Vcb, NewFileInfo, AllocationSize))) {
2018                     AdPrint(("    Error during resize operation (2)\n"));
2019                     try_return(RC);
2020                 }
2021             }*/
2022             NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFSysGetAllocSize(Vcb, AllocationSize);
2023             NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
2024             NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = 0 /*AllocationSize*/;
2025             PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE;
2026             MmPrint(("    CcSetFileSizes()\n"));
2027             CcSetFileSizes(PtrNewFileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize));
2028             NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_MODIFIED;
2029             // Release PagingIoResource
2030             UDFReleaseResource(PagingIoRes);
2031             PagingIoRes = NULL;
2032 
2033             if(NT_SUCCESS(RC)) {
2034                 FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
2035                 if (RequestedDisposition == FILE_SUPERSEDE) {
2036                     // Set attributes for the file ...
2037                     UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
2038                                        NewFileInfo->Dloc->FileEntry, FileAttributes);
2039                     ReturnedInformation = FILE_SUPERSEDED;
2040                 } else {
2041                     // Get attributes for the file ...
2042                     FileAttributes |= TmpFileAttributes;
2043                     // Set attributes for the file ...
2044                     UDFAttributesToUDF(UDFDirIndex(UDFGetDirIndexByFileInfo(NewFileInfo), NewFileInfo->Index),
2045                                        NewFileInfo->Dloc->FileEntry, FileAttributes);
2046                     ReturnedInformation = FILE_OVERWRITTEN;
2047                 }
2048             }
2049             // notify changes
2050             UDFNotifyFullReportChange( Vcb, NewFileInfo,
2051                                        FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE,
2052                                        FILE_ACTION_MODIFIED);
2053 
2054             // Update parent object
2055             if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_WRITE) &&
2056                PtrRelatedFCB &&
2057                PtrRelatedFileObject &&
2058                (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
2059                 PtrRelatedFileObject->Flags |= (FO_FILE_MODIFIED | FO_FILE_SIZE_CHANGED);
2060             }
2061 #else //UDF_READ_ONLY_BUILD
2062             try_return(RC = STATUS_ACCESS_DENIED);
2063 #endif //UDF_READ_ONLY_BUILD
2064         } else {
2065             ReturnedInformation = FILE_OPENED;
2066         }
2067 
2068         // Update parent object
2069         if((Vcb->CompatFlags & UDF_VCB_IC_UPDATE_DIR_READ) &&
2070            PtrRelatedFCB &&
2071            PtrRelatedFileObject &&
2072            (PtrRelatedFCB->FileInfo == NewFileInfo->ParentFile)) {
2073             PtrRelatedFileObject->Flags |= FO_FILE_FAST_IO_READ;
2074         }
2075 
2076 try_exit:   NOTHING;
2077 
2078     } _SEH2_FINALLY {
2079         // Complete the request unless we are here as part of unwinding
2080         //  when an exception condition was encountered, OR
2081         //  if the request has been deferred (i.e. posted for later handling)
2082 
2083         if(RestoreVCBOpenCounter) {
2084             UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
2085             RestoreVCBOpenCounter = FALSE;
2086         }
2087 
2088         if (RC != STATUS_PENDING) {
2089             // If any intermediate (directory) open operations were performed,
2090             //  implement the corresponding close (do *not* however close
2091             //  the target we have opened on behalf of the caller ...).
2092 
2093 #if 0
2094             if(NT_SUCCESS(RC)) {
2095                 CollectStatistics2(Vcb, SuccessfulCreates);
2096             } else {
2097                 CollectStatistics2(Vcb, FailedCreates);
2098             }
2099 #endif
2100 
2101             if (NT_SUCCESS(RC) && PtrNewFcb) {
2102                 // Update the file object such that:
2103                 //  (a) the FsContext field points to the NTRequiredFCB field
2104                 //       in the FCB
2105                 //  (b) the FsContext2 field points to the CCB created as a
2106                 //       result of the open operation
2107 
2108                 // If write-through was requested, then mark the file object
2109                 //  appropriately
2110 
2111                 // directories are not cached
2112                 // so we should prevent flush attepmts on cleanup
2113                 if(!(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)) {
2114 #ifndef UDF_READ_ONLY_BUILD
2115                     if(WriteThroughRequested) {
2116                         PtrNewFileObject->Flags |= FO_WRITE_THROUGH;
2117                         PtrNewFcb->FCBFlags |= UDF_FCB_WRITE_THROUGH;
2118                         MmPrint(("        FO_WRITE_THROUGH\n"));
2119                     }
2120 #endif //UDF_READ_ONLY_BUILD
2121                     if(SequentialIoRequested &&
2122                        !(Vcb->CompatFlags & UDF_VCB_IC_IGNORE_SEQUENTIAL_IO)) {
2123                         PtrNewFileObject->Flags |= FO_SEQUENTIAL_ONLY;
2124                         MmPrint(("        FO_SEQUENTIAL_ONLY\n"));
2125 #ifndef UDF_READ_ONLY_BUILD
2126                         if(Vcb->TargetDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
2127                             PtrNewFileObject->Flags &= ~FO_WRITE_THROUGH;
2128                             PtrNewFcb->FCBFlags &= ~UDF_FCB_WRITE_THROUGH;
2129                             MmPrint(("        FILE_REMOVABLE_MEDIA + FO_SEQUENTIAL_ONLY => ~FO_WRITE_THROUGH\n"));
2130                         }
2131 #endif //UDF_READ_ONLY_BUILD
2132                         if(PtrNewFcb->FileInfo) {
2133                             UDFSetFileAllocMode__(PtrNewFcb->FileInfo, EXTENT_FLAG_ALLOC_SEQUENTIAL);
2134                         }
2135                     }
2136                     if(NoBufferingSpecified) {
2137                         PtrNewFileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
2138                         MmPrint(("        FO_NO_INTERMEDIATE_BUFFERING\n"));
2139                     } else {
2140                         PtrNewFileObject->Flags |= FO_CACHE_SUPPORTED;
2141                         MmPrint(("        FO_CACHE_SUPPORTED\n"));
2142                     }
2143                 }
2144 
2145                 if((DesiredAccess & FILE_EXECUTE) /*&&
2146                    !(PtrNewFcb->FCBFlags & UDF_FCB_DIRECTORY)*/) {
2147                     MmPrint(("        FO_FILE_FAST_IO_READ\n"));
2148                     PtrNewFileObject->Flags |= FO_FILE_FAST_IO_READ;
2149                 }
2150                 // All right. Now we can safely increment OpenHandleCount
2151                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBHandleCount));
2152                 UDFInterlockedIncrement((PLONG)&(PtrNewFcb->OpenHandleCount));
2153 
2154                 if(PtrNewFileObject->Flags & FO_CACHE_SUPPORTED)
2155                     UDFInterlockedIncrement((PLONG)&(PtrNewFcb->CachedOpenHandleCount));
2156                 // Store some flags in CCB
2157                 if(PtrNewCcb) {
2158                     PtrNewCcb->TreeLength = TreeLength;
2159                     // delete on close
2160 #ifndef UDF_READ_ONLY_BUILD
2161                     if(DeleteOnCloseSpecified) {
2162                         ASSERT(!(PtrNewFcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
2163                         PtrNewCcb->CCBFlags |= UDF_CCB_DELETE_ON_CLOSE;
2164                     }
2165 #endif //UDF_READ_ONLY_BUILD
2166                     // case sensetivity
2167                     if(!IgnoreCase) {
2168                         // remember this for possible Rename/Move operation
2169                         PtrNewCcb->CCBFlags |= UDF_CCB_CASE_SENSETIVE;
2170                         PtrNewFileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
2171                     }
2172                     if(IsFileObjectReadOnly(PtrNewFileObject)) {
2173                         UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCountRO));
2174                         PtrNewCcb->CCBFlags |= UDF_CCB_READ_ONLY;
2175                     }
2176                 } else {
2177                     BrutePoint();
2178                 }
2179                 // it was a stream...
2180                 if(StreamOpen)
2181                     PtrNewFileObject->Flags |= FO_STREAM_FILE;
2182 //                PtrNewCcb->CCBFlags |= UDF_CCB_VALID;
2183                 // increment the number of outstanding open operations on this
2184                 // logical volume (i.e. volume cannot be dismounted)
2185                 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount));
2186                 PtrNewFcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
2187                 PtrNewFcb->FCBFlags |= UDF_FCB_VALID;
2188 #ifdef UDF_DBG
2189                 // We have no FileInfo for Volume
2190                 if(PtrNewFcb->FileInfo) {
2191                     ASSERT_REF(PtrNewFcb->ReferenceCount >= PtrNewFcb->FileInfo->RefCount);
2192                 }
2193 #endif // UDF_DBG
2194                 AdPrint(("    FCB %x, CCB %x, FO %x, Flags %x\n", PtrNewFcb, PtrNewCcb, PtrNewFileObject, PtrNewFcb->FCBFlags));
2195 
2196                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2197 
2198             } else if(!NT_SUCCESS(RC)) {
2199                 // Perform failure related post-processing now
2200                 if(RestoreShareAccess && NtReqFcb && PtrNewFileObject) {
2201                     IoRemoveShareAccess(PtrNewFileObject, &(NtReqFcb->FCBShareAccess));
2202                 }
2203                 UDFCleanUpCCB(PtrNewCcb);
2204                 if(PtrNewFileObject) {
2205                     PtrNewFileObject->FsContext2 = NULL;
2206                 }
2207                 // We have successfully opened LastGoodFileInfo,
2208                 // so mark it as VALID to avoid future troubles...
2209                 if(LastGoodFileInfo && LastGoodFileInfo->Fcb) {
2210                     LastGoodFileInfo->Fcb->FCBFlags |= UDF_FCB_VALID;
2211                     if(LastGoodFileInfo->Fcb->NTRequiredFCB) {
2212                         LastGoodFileInfo->Fcb->NTRequiredFCB->NtReqFCBFlags |= UDF_NTREQ_FCB_VALID;
2213                     }
2214                 }
2215                 // Release resources...
2216                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2217                 ASSERT(AcquiredVcb);
2218                 // close the chain
2219                 UDFCloseFileInfoChain(Vcb, LastGoodFileInfo, TreeLength, TRUE);
2220                 // cleanup FCBs (if any)
2221                 if(  Vcb && (PtrNewFcb != Vcb->RootDirFCB) &&
2222                      LastGoodFileInfo ) {
2223                     UDFCleanUpFcbChain(Vcb, LastGoodFileInfo, TreeLength, TRUE);
2224                 } else {
2225                     ASSERT(!LastGoodFileInfo);
2226                 }
2227             } else {
2228                 UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2229             }
2230             // As long as this unwinding is not being performed as a result of
2231             //  an exception condition, complete the IRP ...
2232             if (!_SEH2_AbnormalTermination()) {
2233                 Irp->IoStatus.Status = RC;
2234                 Irp->IoStatus.Information = ReturnedInformation;
2235 
2236                 // complete the IRP
2237                 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
2238                 // Free up the Irp Context
2239                 UDFReleaseIrpContext(PtrIrpContext);
2240             }
2241         } else {
2242             UDFReleaseResFromCreate(&PagingIoRes, &Res1, &Res2);
2243         }
2244 
2245         if(AcquiredVcb) {
2246             UDFReleaseResource(&(Vcb->VCBResource));
2247         }
2248         // free allocated tmp buffers (if any)
2249         if(AbsolutePathName.Buffer)
2250             MyFreePool__(AbsolutePathName.Buffer);
2251         if(LocalPath.Buffer)
2252             MyFreePool__(LocalPath.Buffer);
2253         if(TailNameBuffer)
2254             MyFreePool__(TailNameBuffer);
2255     } _SEH2_END;
2256 
2257     return(RC);
2258 } // end UDFCommonCreate()
2259 
2260 /*************************************************************************
2261 *
2262 * Function: UDFFirstOpenFile()
2263 *
2264 * Description:
2265 *   Perform first Open/Create initialization.
2266 *
2267 * Expected Interrupt Level (for execution) :
2268 *
2269 *  IRQL_PASSIVE_LEVEL
2270 *
2271 * Return Value: STATUS_SUCCESS/Error
2272 *
2273 *************************************************************************/
2274 NTSTATUS
2275 UDFFirstOpenFile(
2276     IN PVCB                    Vcb,                // volume control block
2277     IN PFILE_OBJECT            PtrNewFileObject,   // I/O Mgr. created file object
2278    OUT PtrUDFFCB*              PtrNewFcb,
2279     IN PUDF_FILE_INFO          RelatedFileInfo,
2280     IN PUDF_FILE_INFO          NewFileInfo,
2281     IN PUNICODE_STRING         LocalPath,
2282     IN PUNICODE_STRING         CurName
2283     )
2284 {
2285 //    DIR_INDEX           NewFileIndex;
2286     PtrUDFObjectName    NewFCBName;
2287     PtrUDFNTRequiredFCB NtReqFcb;
2288     NTSTATUS            RC;
2289     BOOLEAN             Linked = TRUE;
2290     PDIR_INDEX_HDR      hDirIndex;
2291     PDIR_INDEX_ITEM     DirIndex;
2292 
2293     AdPrint(("UDFFirstOpenFile\n"));
2294 
2295     if(!((*PtrNewFcb) = UDFAllocateFCB())) {
2296         AdPrint(("Can't allocate FCB\n"));
2297         return STATUS_INSUFFICIENT_RESOURCES;
2298     }
2299 
2300     // Allocate and set new FCB unique name (equal to absolute path name)
2301     if(!(NewFCBName = UDFAllocateObjectName())) return STATUS_INSUFFICIENT_RESOURCES;
2302 
2303     if(RelatedFileInfo && RelatedFileInfo->Fcb &&
2304        !(RelatedFileInfo->Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY)) {
2305         RC = MyCloneUnicodeString(&(NewFCBName->ObjectName), &(RelatedFileInfo->Fcb->FCBName->ObjectName));
2306     } else {
2307         RC = MyInitUnicodeString(&(NewFCBName->ObjectName), L"");
2308     }
2309     if(!NT_SUCCESS(RC))
2310         return STATUS_INSUFFICIENT_RESOURCES;
2311     if( (CurName->Buffer[0] != L':') &&
2312         (!LocalPath->Length ||
2313             ((LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L':') /*&&
2314              (LocalPath->Buffer[LocalPath->Length/sizeof(WCHAR)-1] != L'\\')*/) )) {
2315         RC = MyAppendUnicodeToString(&(NewFCBName->ObjectName), L"\\");
2316         if(!NT_SUCCESS(RC)) {
2317             UDFReleaseObjectName(NewFCBName);
2318             return STATUS_INSUFFICIENT_RESOURCES;
2319         }
2320     }
2321 
2322     // Make link between Fcb and FileInfo
2323     (*PtrNewFcb)->FileInfo = NewFileInfo;
2324     NewFileInfo->Fcb = (*PtrNewFcb);
2325     (*PtrNewFcb)->ParentFcb = RelatedFileInfo->Fcb;
2326 
2327     if(!((*PtrNewFcb)->NTRequiredFCB = NewFileInfo->Dloc->CommonFcb)) {
2328         (*PtrNewFcb)->NTRequiredFCB = (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
2329         if(!((*PtrNewFcb)->NTRequiredFCB)) {
2330             UDFReleaseObjectName(NewFCBName);
2331             return STATUS_INSUFFICIENT_RESOURCES;
2332         }
2333 
2334         UDFPrint(("UDFAllocateNtReqFCB: %x\n", (*PtrNewFcb)->NTRequiredFCB));
2335         RtlZeroMemory((*PtrNewFcb)->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
2336         (*PtrNewFcb)->FileInfo->Dloc->CommonFcb = (*PtrNewFcb)->NTRequiredFCB;
2337         Linked = FALSE;
2338     } else {
2339         if(!(NewFileInfo->Dloc->CommonFcb->NtReqFCBFlags & UDF_NTREQ_FCB_VALID)) {
2340             (*PtrNewFcb)->NTRequiredFCB = NULL;
2341             BrutePoint();
2342             UDFReleaseObjectName(NewFCBName);
2343             return STATUS_ACCESS_DENIED;
2344         }
2345     }
2346 
2347     NtReqFcb = (*PtrNewFcb)->NTRequiredFCB;
2348     // Set times
2349     if(!Linked) {
2350         UDFGetFileXTime((*PtrNewFcb)->FileInfo,
2351             &(NtReqFcb->CreationTime.QuadPart),
2352             &(NtReqFcb->LastAccessTime.QuadPart),
2353             &(NtReqFcb->ChangeTime.QuadPart),
2354             &(NtReqFcb->LastWriteTime.QuadPart) );
2355 
2356         // Set the allocation size for the object is specified
2357         NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart =
2358             UDFSysGetAllocSize(Vcb, NewFileInfo->Dloc->DataLoc.Length);
2359 //        NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart = UDFGetFileAllocationSize(Vcb, NewFileInfo);
2360         NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
2361         NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = NewFileInfo->Dloc->DataLoc.Length;
2362     }
2363     // begin transaction
2364     UDFAcquireResourceExclusive(&(Vcb->FcbListResource), TRUE);
2365 
2366     RC = UDFInitializeFCB(*PtrNewFcb, Vcb, NewFCBName,
2367                  UDFIsADirectory(NewFileInfo) ? UDF_FCB_DIRECTORY : 0, PtrNewFileObject);
2368     if(!NT_SUCCESS(RC)) {
2369         if(!Linked) {
2370             MyFreePool__((*PtrNewFcb)->NTRequiredFCB);
2371             (*PtrNewFcb)->NTRequiredFCB = NULL;
2372         }
2373         UDFReleaseResource(&(Vcb->FcbListResource));
2374         return RC;
2375     }
2376     // set Read-only attribute
2377     if(!UDFIsAStreamDir(NewFileInfo)) {
2378         hDirIndex = UDFGetDirIndexByFileInfo(NewFileInfo);
2379 #ifdef UDF_DBG
2380         if(!hDirIndex) {
2381             BrutePoint();
2382         } else {
2383 #endif // UDF_DBG
2384             if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, NewFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) {
2385                 (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY;
2386             }
2387             MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), &(DirIndex->FName), MEM_USOBJ_TAG);
2388 #ifdef UDF_DBG
2389         }
2390 #endif // UDF_DBG
2391     } else if (RelatedFileInfo->ParentFile) {
2392         hDirIndex = UDFGetDirIndexByFileInfo(RelatedFileInfo);
2393         if(UDFAttributesToNT(DirIndex = UDFDirIndex(hDirIndex, RelatedFileInfo->Index),NULL) & FILE_ATTRIBUTE_READONLY) {
2394             (*PtrNewFcb)->FCBFlags |= UDF_FCB_READ_ONLY;
2395         }
2396         RC = MyAppendUnicodeStringToStringTag(&(NewFCBName->ObjectName), CurName, MEM_USOBJ_TAG);
2397 //    } else {
2398 //        BrutePoint();
2399     }
2400     // do not allocate CCB if it is internal Create/Open
2401     if(NT_SUCCESS(RC)) {
2402         if(PtrNewFileObject) {
2403             RC = UDFOpenFile(Vcb, PtrNewFileObject, *PtrNewFcb);
2404         } else {
2405             RC = STATUS_SUCCESS;
2406         }
2407     }
2408     UDFReleaseResource(&(Vcb->FcbListResource));
2409     // end transaction
2410 
2411 //    if(!NT_SUCCESS(RC)) return RC;
2412 
2413     return RC;
2414 } // end UDFFirstOpenFile()
2415 
2416 /*************************************************************************
2417 *
2418 * Function: UDFOpenFile()
2419 *
2420 * Description:
2421 *   Open a file/dir for the caller.
2422 *
2423 * Expected Interrupt Level (for execution) :
2424 *
2425 *  IRQL_PASSIVE_LEVEL
2426 *
2427 * Return Value: STATUS_SUCCESS/Error
2428 *
2429 *************************************************************************/
2430 NTSTATUS
2431 UDFOpenFile(
2432     PVCB                 Vcb,                // volume control block
2433     PFILE_OBJECT         PtrNewFileObject,   // I/O Mgr. created file object
2434     PtrUDFFCB            PtrNewFcb
2435     )
2436 {
2437     NTSTATUS                RC = STATUS_SUCCESS;
2438     PtrUDFCCB               Ccb = NULL;
2439     PtrUDFNTRequiredFCB     NtReqFcb;
2440 
2441     AdPrint(("UDFOpenFile\n"));
2442     ASSERT((PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB)
2443          ||(PtrNewFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB));
2444 
2445     _SEH2_TRY {
2446 
2447 #if 0
2448         CollectStatistics2(Vcb, CreateHits);
2449 #endif
2450         // create a new CCB structure
2451         if (!(Ccb = UDFAllocateCCB())) {
2452             AdPrint(("Can't allocate CCB\n"));
2453             PtrNewFileObject->FsContext2 = NULL;
2454             //
2455             UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
2456             UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
2457             RC = STATUS_INSUFFICIENT_RESOURCES;
2458             try_return(RC);
2459         }
2460         // initialize the CCB
2461         Ccb->Fcb = PtrNewFcb;
2462         // initialize the CCB to point to the file object
2463         Ccb->FileObject = PtrNewFileObject;
2464 
2465         // initialize the file object appropriately
2466         PtrNewFileObject->FsContext2 = (PVOID)(Ccb);
2467         PtrNewFileObject->Vpb = Vcb->Vpb;
2468         PtrNewFileObject->FsContext = (PVOID)(NtReqFcb = PtrNewFcb->NTRequiredFCB);
2469         PtrNewFileObject->SectionObjectPointer = &(NtReqFcb->SectionObject);
2470 #ifdef DBG
2471 //        NtReqFcb ->FileObject = PtrNewFileObject;
2472 #endif //DBG
2473 
2474 #ifdef UDF_DELAYED_CLOSE
2475         PtrNewFcb->FCBFlags &= ~UDF_FCB_DELAY_CLOSE;
2476 #endif //UDF_DELAYED_CLOSE
2477 
2478         UDFAcquireResourceExclusive(&(PtrNewFcb->CcbListResource),TRUE);
2479         // insert CCB into linked list of open file object to Fcb or
2480         // to Vcb and do other intialization
2481         InsertTailList(&(PtrNewFcb->NextCCB), &(Ccb->NextCCB));
2482         UDFInterlockedIncrement((PLONG)&(PtrNewFcb->ReferenceCount));
2483         UDFInterlockedIncrement((PLONG)&(PtrNewFcb->NTRequiredFCB->CommonRefCount));
2484         UDFReleaseResource(&(PtrNewFcb->CcbListResource));
2485 
2486 try_exit:   NOTHING;
2487     } _SEH2_FINALLY {
2488         NOTHING;
2489     } _SEH2_END;
2490 
2491     return(RC);
2492 } // end UDFOpenFile()
2493 
2494 
2495 /*************************************************************************
2496 *
2497 * Function: UDFInitializeFCB()
2498 *
2499 * Description:
2500 *   Initialize a new FCB structure and also the sent-in file object
2501 *   (if supplied)
2502 *
2503 * Expected Interrupt Level (for execution) :
2504 *
2505 *  IRQL_PASSIVE_LEVEL
2506 *
2507 * Return Value: None
2508 *
2509 *************************************************************************/
2510 NTSTATUS
2511 UDFInitializeFCB(
2512     IN PtrUDFFCB        PtrNewFcb,      // FCB structure to be initialized
2513     IN PVCB             Vcb,            // logical volume (VCB) pointer
2514     IN PtrUDFObjectName PtrObjectName,  // name of the object
2515     IN ULONG            Flags,          // is this a file/directory, etc.
2516     IN PFILE_OBJECT     FileObject)     // optional file object to be initialized
2517 {
2518     AdPrint(("UDFInitializeFCB\n"));
2519     NTSTATUS status;
2520     BOOLEAN Linked = TRUE;
2521 
2522     if(!PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource) {
2523         // record signature
2524         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode = UDF_NODE_TYPE_NT_REQ_FCB;
2525         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeByteSize = sizeof(UDFNTRequiredFCB);
2526         // Initialize the ERESOURCE objects
2527         if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->MainResource)))) {
2528             AdPrint(("    Can't init resource\n"));
2529             return status;
2530         }
2531         if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->NTRequiredFCB->PagingIoResource)))) {
2532             AdPrint(("    Can't init resource (2)\n"));
2533             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource));
2534             return status;
2535         }
2536         // Fill NT required Fcb part
2537         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource = &(PtrNewFcb->NTRequiredFCB->MainResource);
2538         PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = &(PtrNewFcb->NTRequiredFCB->PagingIoResource);
2539         // Itialize byte-range locks support structure
2540         FsRtlInitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock),NULL,NULL);
2541         // Init reference counter
2542         PtrNewFcb->NTRequiredFCB->CommonRefCount = 0;
2543         Linked = FALSE;
2544     } else {
2545         ASSERT(PtrNewFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode == UDF_NODE_TYPE_NT_REQ_FCB);
2546     }
2547     if(!NT_SUCCESS(status = UDFInitializeResourceLite(&(PtrNewFcb->CcbListResource)))) {
2548         AdPrint(("    Can't init resource (3)\n"));
2549         BrutePoint();
2550         if(!Linked) {
2551             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->PagingIoResource));
2552             UDFDeleteResource(&(PtrNewFcb->NTRequiredFCB->MainResource));
2553             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.Resource =
2554             PtrNewFcb->NTRequiredFCB->CommonFCBHeader.PagingIoResource = NULL;
2555             FsRtlUninitializeFileLock(&(PtrNewFcb->NTRequiredFCB->FileLock));
2556         }
2557         return status;
2558     }
2559 
2560     // caller MUST ensure that VCB has been acquired exclusively
2561     InsertTailList(&(Vcb->NextFCB), &(PtrNewFcb->NextFCB));
2562 
2563     // initialize the various list heads
2564     InitializeListHead(&(PtrNewFcb->NextCCB));
2565 
2566     PtrNewFcb->ReferenceCount = 0;
2567     PtrNewFcb->OpenHandleCount = 0;
2568 
2569     PtrNewFcb->FCBFlags = Flags | UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE;
2570 
2571     PtrNewFcb->FCBName = PtrObjectName;
2572 
2573     PtrNewFcb->Vcb = Vcb;
2574 
2575     return STATUS_SUCCESS;
2576 } // end UDFInitializeFCB()
2577 
2578