xref: /reactos/drivers/filesystems/udfs/misc.cpp (revision 34593d93)
1*c2c66affSColin Finck ////////////////////////////////////////////////////////////////////
2*c2c66affSColin Finck // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3*c2c66affSColin Finck // All rights reserved
4*c2c66affSColin Finck // This file was released under the GPLv2 on June 2015.
5*c2c66affSColin Finck ////////////////////////////////////////////////////////////////////
6*c2c66affSColin Finck /*
7*c2c66affSColin Finck 
8*c2c66affSColin Finck  File: Misc.cpp
9*c2c66affSColin Finck 
10*c2c66affSColin Finck  Module: UDF File System Driver (Kernel mode execution only)
11*c2c66affSColin Finck 
12*c2c66affSColin Finck  Description:
13*c2c66affSColin Finck    This file contains some miscellaneous support routines.
14*c2c66affSColin Finck 
15*c2c66affSColin Finck */
16*c2c66affSColin Finck 
17*c2c66affSColin Finck #include            "udffs.h"
18*c2c66affSColin Finck // define the file specific bug-check id
19*c2c66affSColin Finck #define         UDF_BUG_CHECK_ID                UDF_FILE_MISC
20*c2c66affSColin Finck 
21*c2c66affSColin Finck #include            <stdio.h>
22*c2c66affSColin Finck 
23*c2c66affSColin Finck //CCHAR   DefLetter[] = {""};
24*c2c66affSColin Finck 
25*c2c66affSColin Finck /*
26*c2c66affSColin Finck 
27*c2c66affSColin Finck  Function: UDFInitializeZones()
28*c2c66affSColin Finck 
29*c2c66affSColin Finck  Description:
30*c2c66affSColin Finck    Allocates some memory for global zones used to allocate FSD structures.
31*c2c66affSColin Finck    Either all memory will be allocated or we will back out gracefully.
32*c2c66affSColin Finck 
33*c2c66affSColin Finck  Expected Interrupt Level (for execution) :
34*c2c66affSColin Finck 
35*c2c66affSColin Finck   IRQL_PASSIVE_LEVEL
36*c2c66affSColin Finck 
37*c2c66affSColin Finck  Return Value: STATUS_SUCCESS/Error
38*c2c66affSColin Finck 
39*c2c66affSColin Finck */
40*c2c66affSColin Finck NTSTATUS
UDFInitializeZones(VOID)41*c2c66affSColin Finck UDFInitializeZones(VOID)
42*c2c66affSColin Finck {
43*c2c66affSColin Finck     NTSTATUS            RC = STATUS_SUCCESS;
44*c2c66affSColin Finck     uint32              SizeOfZone = UDFGlobalData.DefaultZoneSizeInNumStructs;
45*c2c66affSColin Finck     uint32              SizeOfObjectNameZone = 0;
46*c2c66affSColin Finck     uint32              SizeOfCCBZone = 0;
47*c2c66affSColin Finck //    uint32              SizeOfFCBZone = 0;
48*c2c66affSColin Finck     uint32              SizeOfIrpContextZone = 0;
49*c2c66affSColin Finck //    uint32              SizeOfFileInfoZone = 0;
50*c2c66affSColin Finck 
51*c2c66affSColin Finck     _SEH2_TRY {
52*c2c66affSColin Finck 
53*c2c66affSColin Finck         // initialize the spinlock protecting the zones
54*c2c66affSColin Finck         KeInitializeSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock));
55*c2c66affSColin Finck 
56*c2c66affSColin Finck         // determine memory requirements
57*c2c66affSColin Finck         switch (MmQuerySystemSize()) {
58*c2c66affSColin Finck         case MmMediumSystem:
59*c2c66affSColin Finck             SizeOfObjectNameZone = (4 * SizeOfZone * UDFQuadAlign(sizeof(UDFObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
60*c2c66affSColin Finck             SizeOfCCBZone = (4 * SizeOfZone * UDFQuadAlign(sizeof(UDFCCB))) + sizeof(ZONE_SEGMENT_HEADER);
61*c2c66affSColin Finck             SizeOfIrpContextZone = (4 * SizeOfZone * UDFQuadAlign(sizeof(UDFIrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
62*c2c66affSColin Finck             UDFGlobalData.MaxDelayedCloseCount = 24;
63*c2c66affSColin Finck             UDFGlobalData.MinDelayedCloseCount = 6;
64*c2c66affSColin Finck             UDFGlobalData.MaxDirDelayedCloseCount = 8;
65*c2c66affSColin Finck             UDFGlobalData.MinDirDelayedCloseCount = 2;
66*c2c66affSColin Finck             UDFGlobalData.WCacheMaxFrames = 8*4;
67*c2c66affSColin Finck             UDFGlobalData.WCacheMaxBlocks = 16*64;
68*c2c66affSColin Finck             UDFGlobalData.WCacheBlocksPerFrameSh = 8;
69*c2c66affSColin Finck             UDFGlobalData.WCacheFramesToKeepFree = 4;
70*c2c66affSColin Finck             break;
71*c2c66affSColin Finck         case MmLargeSystem:
72*c2c66affSColin Finck             SizeOfObjectNameZone = (8 * SizeOfZone * UDFQuadAlign(sizeof(UDFObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
73*c2c66affSColin Finck             SizeOfCCBZone = (8 * SizeOfZone * UDFQuadAlign(sizeof(UDFCCB))) + sizeof(ZONE_SEGMENT_HEADER);
74*c2c66affSColin Finck             SizeOfIrpContextZone = (8 * SizeOfZone * UDFQuadAlign(sizeof(UDFIrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
75*c2c66affSColin Finck             UDFGlobalData.MaxDelayedCloseCount = 72;
76*c2c66affSColin Finck             UDFGlobalData.MinDelayedCloseCount = 18;
77*c2c66affSColin Finck             UDFGlobalData.MaxDirDelayedCloseCount = 24;
78*c2c66affSColin Finck             UDFGlobalData.MinDirDelayedCloseCount = 6;
79*c2c66affSColin Finck             UDFGlobalData.WCacheMaxFrames = 2*16*4;
80*c2c66affSColin Finck             UDFGlobalData.WCacheMaxBlocks = 2*16*64;
81*c2c66affSColin Finck             UDFGlobalData.WCacheBlocksPerFrameSh = 8;
82*c2c66affSColin Finck             UDFGlobalData.WCacheFramesToKeepFree = 8;
83*c2c66affSColin Finck             break;
84*c2c66affSColin Finck         case MmSmallSystem:
85*c2c66affSColin Finck         default:
86*c2c66affSColin Finck             SizeOfObjectNameZone = (2 * SizeOfZone * UDFQuadAlign(sizeof(UDFObjectName))) + sizeof(ZONE_SEGMENT_HEADER);
87*c2c66affSColin Finck             SizeOfCCBZone = (2 * SizeOfZone * UDFQuadAlign(sizeof(UDFCCB))) + sizeof(ZONE_SEGMENT_HEADER);
88*c2c66affSColin Finck             SizeOfIrpContextZone = (2 * SizeOfZone * UDFQuadAlign(sizeof(UDFIrpContext))) + sizeof(ZONE_SEGMENT_HEADER);
89*c2c66affSColin Finck             UDFGlobalData.MaxDelayedCloseCount = 8;
90*c2c66affSColin Finck             UDFGlobalData.MinDelayedCloseCount = 2;
91*c2c66affSColin Finck             UDFGlobalData.MaxDirDelayedCloseCount = 6;
92*c2c66affSColin Finck             UDFGlobalData.MinDirDelayedCloseCount = 1;
93*c2c66affSColin Finck             UDFGlobalData.WCacheMaxFrames = 8*4/2;
94*c2c66affSColin Finck             UDFGlobalData.WCacheMaxBlocks = 16*64/2;
95*c2c66affSColin Finck             UDFGlobalData.WCacheBlocksPerFrameSh = 8;
96*c2c66affSColin Finck             UDFGlobalData.WCacheFramesToKeepFree = 2;
97*c2c66affSColin Finck         }
98*c2c66affSColin Finck 
99*c2c66affSColin Finck         // typical NT methodology (at least until *someone* exposed the "difference" between a server and workstation ;-)
100*c2c66affSColin Finck         if (MmIsThisAnNtAsSystem()) {
101*c2c66affSColin Finck             SizeOfObjectNameZone *= UDF_NTAS_MULTIPLE;
102*c2c66affSColin Finck             SizeOfCCBZone *= UDF_NTAS_MULTIPLE;
103*c2c66affSColin Finck             SizeOfIrpContextZone *= UDF_NTAS_MULTIPLE;
104*c2c66affSColin Finck         }
105*c2c66affSColin Finck 
106*c2c66affSColin Finck         // allocate memory for each of the zones and initialize the zones ...
107*c2c66affSColin Finck         if (!(UDFGlobalData.ObjectNameZone = DbgAllocatePool(NonPagedPool, SizeOfObjectNameZone))) {
108*c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
109*c2c66affSColin Finck             try_return(RC);
110*c2c66affSColin Finck         }
111*c2c66affSColin Finck 
112*c2c66affSColin Finck         if (!(UDFGlobalData.CCBZone = DbgAllocatePool(NonPagedPool, SizeOfCCBZone))) {
113*c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
114*c2c66affSColin Finck             try_return(RC);
115*c2c66affSColin Finck         }
116*c2c66affSColin Finck 
117*c2c66affSColin Finck         if (!(UDFGlobalData.IrpContextZone = DbgAllocatePool(NonPagedPool, SizeOfIrpContextZone))) {
118*c2c66affSColin Finck             RC = STATUS_INSUFFICIENT_RESOURCES;
119*c2c66affSColin Finck             try_return(RC);
120*c2c66affSColin Finck         }
121*c2c66affSColin Finck 
122*c2c66affSColin Finck         // initialize each of the zone headers ...
123*c2c66affSColin Finck         if (!NT_SUCCESS(RC = ExInitializeZone(&(UDFGlobalData.ObjectNameZoneHeader),
124*c2c66affSColin Finck                     UDFQuadAlign(sizeof(UDFObjectName)),
125*c2c66affSColin Finck                     UDFGlobalData.ObjectNameZone, SizeOfObjectNameZone))) {
126*c2c66affSColin Finck             // failed the initialization, leave ...
127*c2c66affSColin Finck             try_return(RC);
128*c2c66affSColin Finck         }
129*c2c66affSColin Finck 
130*c2c66affSColin Finck         if (!NT_SUCCESS(RC = ExInitializeZone(&(UDFGlobalData.CCBZoneHeader),
131*c2c66affSColin Finck                     UDFQuadAlign(sizeof(UDFCCB)),
132*c2c66affSColin Finck                     UDFGlobalData.CCBZone,
133*c2c66affSColin Finck                     SizeOfCCBZone))) {
134*c2c66affSColin Finck             // failed the initialization, leave ...
135*c2c66affSColin Finck             try_return(RC);
136*c2c66affSColin Finck         }
137*c2c66affSColin Finck 
138*c2c66affSColin Finck         if (!NT_SUCCESS(RC = ExInitializeZone(&(UDFGlobalData.IrpContextZoneHeader),
139*c2c66affSColin Finck                     UDFQuadAlign(sizeof(UDFIrpContext)),
140*c2c66affSColin Finck                     UDFGlobalData.IrpContextZone,
141*c2c66affSColin Finck                     SizeOfIrpContextZone))) {
142*c2c66affSColin Finck             // failed the initialization, leave ...
143*c2c66affSColin Finck             try_return(RC);
144*c2c66affSColin Finck         }
145*c2c66affSColin Finck 
146*c2c66affSColin Finck try_exit:   NOTHING;
147*c2c66affSColin Finck 
148*c2c66affSColin Finck     } _SEH2_FINALLY {
149*c2c66affSColin Finck         if (!NT_SUCCESS(RC)) {
150*c2c66affSColin Finck             // invoke the destroy routine now ...
151*c2c66affSColin Finck             UDFDestroyZones();
152*c2c66affSColin Finck         } else {
153*c2c66affSColin Finck             // mark the fact that we have allocated zones ...
154*c2c66affSColin Finck             UDFSetFlag(UDFGlobalData.UDFFlags, UDF_DATA_FLAGS_ZONES_INITIALIZED);
155*c2c66affSColin Finck         }
156*c2c66affSColin Finck     } _SEH2_END;
157*c2c66affSColin Finck 
158*c2c66affSColin Finck     return(RC);
159*c2c66affSColin Finck }
160*c2c66affSColin Finck 
161*c2c66affSColin Finck 
162*c2c66affSColin Finck /*************************************************************************
163*c2c66affSColin Finck *
164*c2c66affSColin Finck * Function: UDFDestroyZones()
165*c2c66affSColin Finck *
166*c2c66affSColin Finck * Description:
167*c2c66affSColin Finck *   Free up the previously allocated memory. NEVER do this once the
168*c2c66affSColin Finck *   driver has been successfully loaded.
169*c2c66affSColin Finck *
170*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
171*c2c66affSColin Finck *
172*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
173*c2c66affSColin Finck *
174*c2c66affSColin Finck * Return Value: None
175*c2c66affSColin Finck *
176*c2c66affSColin Finck *************************************************************************/
UDFDestroyZones(VOID)177*c2c66affSColin Finck VOID UDFDestroyZones(VOID)
178*c2c66affSColin Finck {
179*c2c66affSColin Finck //    BrutePoint();
180*c2c66affSColin Finck 
181*c2c66affSColin Finck     _SEH2_TRY {
182*c2c66affSColin Finck         // free up each of the pools
183*c2c66affSColin Finck         if(UDFGlobalData.ObjectNameZone) {
184*c2c66affSColin Finck             DbgFreePool(UDFGlobalData.ObjectNameZone);
185*c2c66affSColin Finck             UDFGlobalData.ObjectNameZone = NULL;
186*c2c66affSColin Finck         }
187*c2c66affSColin Finck         if(UDFGlobalData.CCBZone) {
188*c2c66affSColin Finck             DbgFreePool(UDFGlobalData.CCBZone);
189*c2c66affSColin Finck             UDFGlobalData.CCBZone = NULL;
190*c2c66affSColin Finck         }
191*c2c66affSColin Finck         if(UDFGlobalData.IrpContextZone) {
192*c2c66affSColin Finck             DbgFreePool(UDFGlobalData.IrpContextZone);
193*c2c66affSColin Finck             UDFGlobalData.IrpContextZone = NULL;
194*c2c66affSColin Finck         }
195*c2c66affSColin Finck 
196*c2c66affSColin Finck //try_exit: NOTHING;
197*c2c66affSColin Finck 
198*c2c66affSColin Finck     } _SEH2_FINALLY {
199*c2c66affSColin Finck         UDFGlobalData.UDFFlags &= ~UDF_DATA_FLAGS_ZONES_INITIALIZED;
200*c2c66affSColin Finck     } _SEH2_END;
201*c2c66affSColin Finck 
202*c2c66affSColin Finck     return;
203*c2c66affSColin Finck }
204*c2c66affSColin Finck 
205*c2c66affSColin Finck 
206*c2c66affSColin Finck /*************************************************************************
207*c2c66affSColin Finck *
208*c2c66affSColin Finck * Function: UDFIsIrpTopLevel()
209*c2c66affSColin Finck *
210*c2c66affSColin Finck * Description:
211*c2c66affSColin Finck *   Helps the FSD determine who the "top level" caller is for this
212*c2c66affSColin Finck *   request. A request can originate directly from a user process
213*c2c66affSColin Finck *   (in which case, the "top level" will be NULL when this routine
214*c2c66affSColin Finck *   is invoked), OR the user may have originated either from the NT
215*c2c66affSColin Finck *   Cache Manager/VMM ("top level" may be set), or this could be a
216*c2c66affSColin Finck *   recursion into our code in which we would have set the "top level"
217*c2c66affSColin Finck *   field the last time around.
218*c2c66affSColin Finck *
219*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
220*c2c66affSColin Finck *
221*c2c66affSColin Finck *  whatever level a particular dispatch routine is invoked at.
222*c2c66affSColin Finck *
223*c2c66affSColin Finck * Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked)
224*c2c66affSColin Finck *
225*c2c66affSColin Finck *************************************************************************/
226*c2c66affSColin Finck BOOLEAN
227*c2c66affSColin Finck __fastcall
UDFIsIrpTopLevel(PIRP Irp)228*c2c66affSColin Finck UDFIsIrpTopLevel(
229*c2c66affSColin Finck     PIRP            Irp)            // the IRP sent to our dispatch routine
230*c2c66affSColin Finck {
231*c2c66affSColin Finck     if(!IoGetTopLevelIrp()) {
232*c2c66affSColin Finck         // OK, so we can set ourselves to become the "top level" component
233*c2c66affSColin Finck         IoSetTopLevelIrp(Irp);
234*c2c66affSColin Finck         return TRUE;
235*c2c66affSColin Finck     }
236*c2c66affSColin Finck     return FALSE;
237*c2c66affSColin Finck }
238*c2c66affSColin Finck 
239*c2c66affSColin Finck 
240*c2c66affSColin Finck /*************************************************************************
241*c2c66affSColin Finck *
242*c2c66affSColin Finck * Function: UDFExceptionFilter()
243*c2c66affSColin Finck *
244*c2c66affSColin Finck * Description:
245*c2c66affSColin Finck *   This routines allows the driver to determine whether the exception
246*c2c66affSColin Finck *   is an "allowed" exception i.e. one we should not-so-quietly consume
247*c2c66affSColin Finck *   ourselves, or one which should be propagated onwards in which case
248*c2c66affSColin Finck *   we will most likely bring down the machine.
249*c2c66affSColin Finck *
250*c2c66affSColin Finck *   This routine employs the services of FsRtlIsNtstatusExpected(). This
251*c2c66affSColin Finck *   routine returns a BOOLEAN result. A RC of FALSE will cause us to return
252*c2c66affSColin Finck *   EXCEPTION_CONTINUE_SEARCH which will probably cause a panic.
253*c2c66affSColin Finck *   The FsRtl.. routine returns FALSE iff exception values are (currently) :
254*c2c66affSColin Finck *       STATUS_DATATYPE_MISALIGNMENT    ||  STATUS_ACCESS_VIOLATION ||
255*c2c66affSColin Finck *       STATUS_ILLEGAL_INSTRUCTION  ||  STATUS_INSTRUCTION_MISALIGNMENT
256*c2c66affSColin Finck *
257*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
258*c2c66affSColin Finck *
259*c2c66affSColin Finck *  ?
260*c2c66affSColin Finck *
261*c2c66affSColin Finck * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH
262*c2c66affSColin Finck *
263*c2c66affSColin Finck *************************************************************************/
264*c2c66affSColin Finck long
UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext,PEXCEPTION_POINTERS PtrExceptionPointers)265*c2c66affSColin Finck UDFExceptionFilter(
266*c2c66affSColin Finck     PtrUDFIrpContext    PtrIrpContext,
267*c2c66affSColin Finck     PEXCEPTION_POINTERS PtrExceptionPointers
268*c2c66affSColin Finck     )
269*c2c66affSColin Finck {
270*c2c66affSColin Finck     long                            ReturnCode = EXCEPTION_EXECUTE_HANDLER;
271*c2c66affSColin Finck     NTSTATUS                        ExceptionCode = STATUS_SUCCESS;
272*c2c66affSColin Finck #if defined UDF_DBG || defined PRINT_ALWAYS
273*c2c66affSColin Finck     ULONG i;
274*c2c66affSColin Finck 
275*c2c66affSColin Finck     UDFPrint(("UDFExceptionFilter\n"));
276*c2c66affSColin Finck     UDFPrint(("    Ex. Code: %x\n",PtrExceptionPointers->ExceptionRecord->ExceptionCode));
277*c2c66affSColin Finck     UDFPrint(("    Ex. Addr: %x\n",PtrExceptionPointers->ExceptionRecord->ExceptionAddress));
278*c2c66affSColin Finck     UDFPrint(("    Ex. Flag: %x\n",PtrExceptionPointers->ExceptionRecord->ExceptionFlags));
279*c2c66affSColin Finck     UDFPrint(("    Ex. Pnum: %x\n",PtrExceptionPointers->ExceptionRecord->NumberParameters));
280*c2c66affSColin Finck     for(i=0;i<PtrExceptionPointers->ExceptionRecord->NumberParameters;i++) {
281*c2c66affSColin Finck         UDFPrint(("       %x\n",PtrExceptionPointers->ExceptionRecord->ExceptionInformation[i]));
282*c2c66affSColin Finck     }
283*c2c66affSColin Finck #ifdef _X86_
284*c2c66affSColin Finck     UDFPrint(("Exception context:\n"));
285*c2c66affSColin Finck     if(PtrExceptionPointers->ContextRecord->ContextFlags & CONTEXT_INTEGER) {
286*c2c66affSColin Finck         UDFPrint(("EAX=%8.8x   ",PtrExceptionPointers->ContextRecord->Eax));
287*c2c66affSColin Finck         UDFPrint(("EBX=%8.8x   ",PtrExceptionPointers->ContextRecord->Ebx));
288*c2c66affSColin Finck         UDFPrint(("ECX=%8.8x   ",PtrExceptionPointers->ContextRecord->Ecx));
289*c2c66affSColin Finck         UDFPrint(("EDX=%8.8x\n",PtrExceptionPointers->ContextRecord->Edx));
290*c2c66affSColin Finck 
291*c2c66affSColin Finck         UDFPrint(("ESI=%8.8x   ",PtrExceptionPointers->ContextRecord->Esi));
292*c2c66affSColin Finck         UDFPrint(("EDI=%8.8x   ",PtrExceptionPointers->ContextRecord->Edi));
293*c2c66affSColin Finck     }
294*c2c66affSColin Finck     if(PtrExceptionPointers->ContextRecord->ContextFlags & CONTEXT_CONTROL) {
295*c2c66affSColin Finck         UDFPrint(("EBP=%8.8x   ",PtrExceptionPointers->ContextRecord->Esp));
296*c2c66affSColin Finck         UDFPrint(("ESP=%8.8x\n",PtrExceptionPointers->ContextRecord->Ebp));
297*c2c66affSColin Finck 
298*c2c66affSColin Finck         UDFPrint(("EIP=%8.8x\n",PtrExceptionPointers->ContextRecord->Eip));
299*c2c66affSColin Finck     }
300*c2c66affSColin Finck //    UDFPrint(("Flags: %s %s    ",PtrExceptionPointers->ContextRecord->Eip));
301*c2c66affSColin Finck #endif //_X86_
302*c2c66affSColin Finck 
303*c2c66affSColin Finck #endif // UDF_DBG
304*c2c66affSColin Finck 
305*c2c66affSColin Finck     // figure out the exception code
306*c2c66affSColin Finck     ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionCode;
307*c2c66affSColin Finck 
308*c2c66affSColin Finck     if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && (PtrExceptionPointers->ExceptionRecord->NumberParameters >= 3)) {
309*c2c66affSColin Finck         ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionInformation[2];
310*c2c66affSColin Finck     }
311*c2c66affSColin Finck 
312*c2c66affSColin Finck     if (PtrIrpContext) {
313*c2c66affSColin Finck         PtrIrpContext->SavedExceptionCode = ExceptionCode;
314*c2c66affSColin Finck         UDFSetFlag(PtrIrpContext->IrpContextFlags, UDF_IRP_CONTEXT_EXCEPTION);
315*c2c66affSColin Finck     }
316*c2c66affSColin Finck 
317*c2c66affSColin Finck     // check if we should propagate this exception or not
318*c2c66affSColin Finck     if (!(FsRtlIsNtstatusExpected(ExceptionCode))) {
319*c2c66affSColin Finck 
320*c2c66affSColin Finck         // better free up the IrpContext now ...
321*c2c66affSColin Finck         if (PtrIrpContext) {
322*c2c66affSColin Finck             UDFPrint(("    UDF Driver internal error\n"));
323*c2c66affSColin Finck             BrutePoint();
324*c2c66affSColin Finck         } else {
325*c2c66affSColin Finck             // we are not ok, propagate this exception.
326*c2c66affSColin Finck             //  NOTE: we will bring down the machine ...
327*c2c66affSColin Finck             ReturnCode = EXCEPTION_CONTINUE_SEARCH;
328*c2c66affSColin Finck         }
329*c2c66affSColin Finck     }
330*c2c66affSColin Finck 
331*c2c66affSColin Finck 
332*c2c66affSColin Finck     // return the appropriate code
333*c2c66affSColin Finck     return(ReturnCode);
334*c2c66affSColin Finck } // end UDFExceptionFilter()
335*c2c66affSColin Finck 
336*c2c66affSColin Finck 
337*c2c66affSColin Finck /*************************************************************************
338*c2c66affSColin Finck *
339*c2c66affSColin Finck * Function: UDFExceptionHandler()
340*c2c66affSColin Finck *
341*c2c66affSColin Finck * Description:
342*c2c66affSColin Finck *   One of the routines in the FSD or in the modules we invoked encountered
343*c2c66affSColin Finck *   an exception. We have decided that we will "handle" the exception.
344*c2c66affSColin Finck *   Therefore we will prevent the machine from a panic ...
345*c2c66affSColin Finck *   You can do pretty much anything you choose to in your commercial
346*c2c66affSColin Finck *   driver at this point to ensure a graceful exit. In the UDF
347*c2c66affSColin Finck *   driver, We shall simply free up the IrpContext (if any), set the
348*c2c66affSColin Finck *   error code in the IRP and complete the IRP at this time ...
349*c2c66affSColin Finck *
350*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
351*c2c66affSColin Finck *
352*c2c66affSColin Finck *  ?
353*c2c66affSColin Finck *
354*c2c66affSColin Finck * Return Value: Error code
355*c2c66affSColin Finck *
356*c2c66affSColin Finck *************************************************************************/
357*c2c66affSColin Finck NTSTATUS
UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext,PIRP Irp)358*c2c66affSColin Finck UDFExceptionHandler(
359*c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext,
360*c2c66affSColin Finck     PIRP             Irp
361*c2c66affSColin Finck     )
362*c2c66affSColin Finck {
363*c2c66affSColin Finck //    NTSTATUS                        RC;
364*c2c66affSColin Finck     NTSTATUS            ExceptionCode = STATUS_INSUFFICIENT_RESOURCES;
365*c2c66affSColin Finck     PDEVICE_OBJECT      Device;
366*c2c66affSColin Finck     PVPB Vpb;
367*c2c66affSColin Finck     PETHREAD Thread;
368*c2c66affSColin Finck 
369*c2c66affSColin Finck     UDFPrint(("UDFExceptionHandler \n"));
370*c2c66affSColin Finck 
371*c2c66affSColin Finck //    ASSERT(Irp);
372*c2c66affSColin Finck 
373*c2c66affSColin Finck     if (!Irp) {
374*c2c66affSColin Finck         UDFPrint(("  !Irp, return\n"));
375*c2c66affSColin Finck         ASSERT(!PtrIrpContext);
376*c2c66affSColin Finck         return ExceptionCode;
377*c2c66affSColin Finck     }
378*c2c66affSColin Finck     // If it was a queued close (or something like this) then we need not
379*c2c66affSColin Finck     // completing it because of MUST_SUCCEED requirement.
380*c2c66affSColin Finck 
381*c2c66affSColin Finck     if (PtrIrpContext) {
382*c2c66affSColin Finck         ExceptionCode = PtrIrpContext->SavedExceptionCode;
383*c2c66affSColin Finck         // Free irp context here
384*c2c66affSColin Finck //        UDFReleaseIrpContext(PtrIrpContext);
385*c2c66affSColin Finck     } else {
386*c2c66affSColin Finck         UDFPrint(("  complete Irp and return\n"));
387*c2c66affSColin Finck         // must be insufficient resources ...?
388*c2c66affSColin Finck         ExceptionCode = STATUS_INSUFFICIENT_RESOURCES;
389*c2c66affSColin Finck         Irp->IoStatus.Status = ExceptionCode;
390*c2c66affSColin Finck         Irp->IoStatus.Information = 0;
391*c2c66affSColin Finck         // complete the IRP
392*c2c66affSColin Finck         IoCompleteRequest(Irp, IO_NO_INCREMENT);
393*c2c66affSColin Finck 
394*c2c66affSColin Finck         return ExceptionCode;
395*c2c66affSColin Finck     }
396*c2c66affSColin Finck 
397*c2c66affSColin Finck     //  Check if we are posting this request.  One of the following must be true
398*c2c66affSColin Finck     //  if we are to post a request.
399*c2c66affSColin Finck     //
400*c2c66affSColin Finck     //      - Status code is STATUS_CANT_WAIT and the request is asynchronous
401*c2c66affSColin Finck     //          or we are forcing this to be posted.
402*c2c66affSColin Finck     //
403*c2c66affSColin Finck     //      - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
404*c2c66affSColin Finck     //          or higher.  Can't wait for IO in the verify path in this case.
405*c2c66affSColin Finck     //
406*c2c66affSColin Finck     //  Set the MORE_PROCESSING flag in the IrpContext to keep if from being
407*c2c66affSColin Finck     //  deleted if this is a retryable condition.
408*c2c66affSColin Finck 
409*c2c66affSColin Finck     if (ExceptionCode == STATUS_VERIFY_REQUIRED) {
410*c2c66affSColin Finck         if (KeGetCurrentIrql() >= APC_LEVEL) {
411*c2c66affSColin Finck             UDFPrint(("  use UDFPostRequest()\n"));
412*c2c66affSColin Finck             ExceptionCode = UDFPostRequest( PtrIrpContext, Irp );
413*c2c66affSColin Finck         }
414*c2c66affSColin Finck     }
415*c2c66affSColin Finck 
416*c2c66affSColin Finck     //  If we posted the request or our caller will retry then just return here.
417*c2c66affSColin Finck     if ((ExceptionCode == STATUS_PENDING) ||
418*c2c66affSColin Finck         (ExceptionCode == STATUS_CANT_WAIT)) {
419*c2c66affSColin Finck 
420*c2c66affSColin Finck         UDFPrint(("  STATUS_PENDING/STATUS_CANT_WAIT, return\n"));
421*c2c66affSColin Finck         return ExceptionCode;
422*c2c66affSColin Finck     }
423*c2c66affSColin Finck 
424*c2c66affSColin Finck     //  Store this error into the Irp for posting back to the Io system.
425*c2c66affSColin Finck     Irp->IoStatus.Status = ExceptionCode;
426*c2c66affSColin Finck     if (IoIsErrorUserInduced( ExceptionCode )) {
427*c2c66affSColin Finck 
428*c2c66affSColin Finck         //  Check for the various error conditions that can be caused by,
429*c2c66affSColin Finck         //  and possibly resolved my the user.
430*c2c66affSColin Finck         if (ExceptionCode == STATUS_VERIFY_REQUIRED) {
431*c2c66affSColin Finck 
432*c2c66affSColin Finck             //  Now we are at the top level file system entry point.
433*c2c66affSColin Finck             //
434*c2c66affSColin Finck             //  If we have already posted this request then the device to
435*c2c66affSColin Finck             //  verify is in the original thread.  Find this via the Irp.
436*c2c66affSColin Finck             Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
437*c2c66affSColin Finck             IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );
438*c2c66affSColin Finck 
439*c2c66affSColin Finck             //  If there is no device in that location then check in the
440*c2c66affSColin Finck             //  current thread.
441*c2c66affSColin Finck             if (Device == NULL) {
442*c2c66affSColin Finck 
443*c2c66affSColin Finck                 Device = IoGetDeviceToVerify( PsGetCurrentThread() );
444*c2c66affSColin Finck                 IoSetDeviceToVerify( PsGetCurrentThread(), NULL );
445*c2c66affSColin Finck 
446*c2c66affSColin Finck                 ASSERT( Device != NULL );
447*c2c66affSColin Finck 
448*c2c66affSColin Finck                 //  Let's not BugCheck just because the driver screwed up.
449*c2c66affSColin Finck                 if (Device == NULL) {
450*c2c66affSColin Finck 
451*c2c66affSColin Finck                     UDFPrint(("  Device == NULL, return\n"));
452*c2c66affSColin Finck                     ExceptionCode = STATUS_DRIVER_INTERNAL_ERROR;
453*c2c66affSColin Finck                     Irp->IoStatus.Status = ExceptionCode;
454*c2c66affSColin Finck                     Irp->IoStatus.Information = 0;
455*c2c66affSColin Finck                     // complete the IRP
456*c2c66affSColin Finck                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
457*c2c66affSColin Finck 
458*c2c66affSColin Finck                     UDFReleaseIrpContext(PtrIrpContext);
459*c2c66affSColin Finck 
460*c2c66affSColin Finck                     return ExceptionCode;
461*c2c66affSColin Finck                 }
462*c2c66affSColin Finck             }
463*c2c66affSColin Finck 
464*c2c66affSColin Finck             UDFPrint(("  use UDFPerformVerify()\n"));
465*c2c66affSColin Finck             //  UDFPerformVerify() will do the right thing with the Irp.
466*c2c66affSColin Finck             //  If we return STATUS_CANT_WAIT then the current thread
467*c2c66affSColin Finck             //  can retry the request.
468*c2c66affSColin Finck             return UDFPerformVerify( PtrIrpContext, Irp, Device );
469*c2c66affSColin Finck         }
470*c2c66affSColin Finck 
471*c2c66affSColin Finck         //
472*c2c66affSColin Finck         //  The other user induced conditions generate an error unless
473*c2c66affSColin Finck         //  they have been disabled for this request.
474*c2c66affSColin Finck         //
475*c2c66affSColin Finck 
476*c2c66affSColin Finck         if (FlagOn( PtrIrpContext->IrpContextFlags, UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS )) {
477*c2c66affSColin Finck 
478*c2c66affSColin Finck             UDFPrint(("  DISABLE_POPUPS, complete Irp and return\n"));
479*c2c66affSColin Finck             Irp->IoStatus.Status = ExceptionCode;
480*c2c66affSColin Finck             Irp->IoStatus.Information = 0;
481*c2c66affSColin Finck             // complete the IRP
482*c2c66affSColin Finck             IoCompleteRequest(Irp, IO_NO_INCREMENT);
483*c2c66affSColin Finck 
484*c2c66affSColin Finck             UDFReleaseIrpContext(PtrIrpContext);
485*c2c66affSColin Finck             return ExceptionCode;
486*c2c66affSColin Finck         } else {
487*c2c66affSColin Finck 
488*c2c66affSColin Finck             //  Generate a pop-up
489*c2c66affSColin Finck             if (IoGetCurrentIrpStackLocation( Irp )->FileObject != NULL) {
490*c2c66affSColin Finck 
491*c2c66affSColin Finck                 Vpb = IoGetCurrentIrpStackLocation( Irp )->FileObject->Vpb;
492*c2c66affSColin Finck             } else {
493*c2c66affSColin Finck 
494*c2c66affSColin Finck                 Vpb = NULL;
495*c2c66affSColin Finck             }
496*c2c66affSColin Finck             //  The device to verify is either in my thread local storage
497*c2c66affSColin Finck             //  or that of the thread that owns the Irp.
498*c2c66affSColin Finck             Thread = Irp->Tail.Overlay.Thread;
499*c2c66affSColin Finck             Device = IoGetDeviceToVerify( Thread );
500*c2c66affSColin Finck 
501*c2c66affSColin Finck             if (Device == NULL) {
502*c2c66affSColin Finck 
503*c2c66affSColin Finck                 Thread = PsGetCurrentThread();
504*c2c66affSColin Finck                 Device = IoGetDeviceToVerify( Thread );
505*c2c66affSColin Finck                 ASSERT( Device != NULL );
506*c2c66affSColin Finck 
507*c2c66affSColin Finck                 //  Let's not BugCheck just because the driver screwed up.
508*c2c66affSColin Finck                 if (Device == NULL) {
509*c2c66affSColin Finck                     UDFPrint(("  Device == NULL, return(2)\n"));
510*c2c66affSColin Finck                     Irp->IoStatus.Status = ExceptionCode;
511*c2c66affSColin Finck                     Irp->IoStatus.Information = 0;
512*c2c66affSColin Finck                     // complete the IRP
513*c2c66affSColin Finck                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
514*c2c66affSColin Finck 
515*c2c66affSColin Finck                     UDFReleaseIrpContext(PtrIrpContext);
516*c2c66affSColin Finck 
517*c2c66affSColin Finck                     return ExceptionCode;
518*c2c66affSColin Finck                 }
519*c2c66affSColin Finck             }
520*c2c66affSColin Finck 
521*c2c66affSColin Finck             //  This routine actually causes the pop-up.  It usually
522*c2c66affSColin Finck             //  does this by queuing an APC to the callers thread,
523*c2c66affSColin Finck             //  but in some cases it will complete the request immediately,
524*c2c66affSColin Finck             //  so it is very important to IoMarkIrpPending() first.
525*c2c66affSColin Finck             IoMarkIrpPending( Irp );
526*c2c66affSColin Finck             IoRaiseHardError( Irp, Vpb, Device );
527*c2c66affSColin Finck 
528*c2c66affSColin Finck             //  We will be handing control back to the caller here, so
529*c2c66affSColin Finck             //  reset the saved device object.
530*c2c66affSColin Finck 
531*c2c66affSColin Finck             UDFPrint(("  use IoSetDeviceToVerify()\n"));
532*c2c66affSColin Finck             IoSetDeviceToVerify( Thread, NULL );
533*c2c66affSColin Finck             //  The Irp will be completed by Io or resubmitted.  In either
534*c2c66affSColin Finck             //  case we must clean up the IrpContext here.
535*c2c66affSColin Finck 
536*c2c66affSColin Finck             UDFReleaseIrpContext(PtrIrpContext);
537*c2c66affSColin Finck             return STATUS_PENDING;
538*c2c66affSColin Finck         }
539*c2c66affSColin Finck     }
540*c2c66affSColin Finck 
541*c2c66affSColin Finck     // If it was a normal request from IOManager then complete it
542*c2c66affSColin Finck     if (Irp) {
543*c2c66affSColin Finck         UDFPrint(("  complete Irp\n"));
544*c2c66affSColin Finck         // set the error code in the IRP
545*c2c66affSColin Finck         Irp->IoStatus.Status = ExceptionCode;
546*c2c66affSColin Finck         Irp->IoStatus.Information = 0;
547*c2c66affSColin Finck 
548*c2c66affSColin Finck         // complete the IRP
549*c2c66affSColin Finck         IoCompleteRequest(Irp, IO_NO_INCREMENT);
550*c2c66affSColin Finck 
551*c2c66affSColin Finck         UDFReleaseIrpContext(PtrIrpContext);
552*c2c66affSColin Finck     }
553*c2c66affSColin Finck 
554*c2c66affSColin Finck     UDFPrint(("  return from exception handler with code %x\n", ExceptionCode));
555*c2c66affSColin Finck     return(ExceptionCode);
556*c2c66affSColin Finck } // end UDFExceptionHandler()
557*c2c66affSColin Finck 
558*c2c66affSColin Finck /*************************************************************************
559*c2c66affSColin Finck *
560*c2c66affSColin Finck * Function: UDFLogEvent()
561*c2c66affSColin Finck *
562*c2c66affSColin Finck * Description:
563*c2c66affSColin Finck *   Log a message in the NT Event Log. This is a rather simplistic log
564*c2c66affSColin Finck *   methodology since we can potentially utilize the event log to
565*c2c66affSColin Finck *   provide a lot of information to the user (and you should too!)
566*c2c66affSColin Finck *
567*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
568*c2c66affSColin Finck *
569*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
570*c2c66affSColin Finck *
571*c2c66affSColin Finck * Return Value: None
572*c2c66affSColin Finck *
573*c2c66affSColin Finck *************************************************************************/
574*c2c66affSColin Finck VOID
UDFLogEvent(NTSTATUS UDFEventLogId,NTSTATUS RC)575*c2c66affSColin Finck UDFLogEvent(
576*c2c66affSColin Finck     NTSTATUS UDFEventLogId,      // the UDF private message id
577*c2c66affSColin Finck     NTSTATUS RC)                 // any NT error code we wish to log ...
578*c2c66affSColin Finck {
579*c2c66affSColin Finck     _SEH2_TRY {
580*c2c66affSColin Finck 
581*c2c66affSColin Finck         // Implement a call to IoAllocateErrorLogEntry() followed by a call
582*c2c66affSColin Finck         // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry()
583*c2c66affSColin Finck         // will free memory for the entry once the write completes (which in actuality
584*c2c66affSColin Finck         // is an asynchronous operation).
585*c2c66affSColin Finck 
586*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
587*c2c66affSColin Finck         // nothing really we can do here, just do not wish to crash ...
588*c2c66affSColin Finck         NOTHING;
589*c2c66affSColin Finck     } _SEH2_END;
590*c2c66affSColin Finck 
591*c2c66affSColin Finck     return;
592*c2c66affSColin Finck } // end UDFLogEvent()
593*c2c66affSColin Finck 
594*c2c66affSColin Finck 
595*c2c66affSColin Finck /*************************************************************************
596*c2c66affSColin Finck *
597*c2c66affSColin Finck * Function: UDFAllocateObjectName()
598*c2c66affSColin Finck *
599*c2c66affSColin Finck * Description:
600*c2c66affSColin Finck *   Allocate a new ObjectName structure to represent an open on-disk object.
601*c2c66affSColin Finck *   Also initialize the ObjectName structure to NULL.
602*c2c66affSColin Finck *
603*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
604*c2c66affSColin Finck *
605*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
606*c2c66affSColin Finck *
607*c2c66affSColin Finck * Return Value: A pointer to the ObjectName structure OR NULL.
608*c2c66affSColin Finck *
609*c2c66affSColin Finck *************************************************************************/
610*c2c66affSColin Finck PtrUDFObjectName
UDFAllocateObjectName(VOID)611*c2c66affSColin Finck UDFAllocateObjectName(VOID)
612*c2c66affSColin Finck {
613*c2c66affSColin Finck     PtrUDFObjectName            PtrObjectName = NULL;
614*c2c66affSColin Finck     BOOLEAN                     AllocatedFromZone = TRUE;
615*c2c66affSColin Finck     KIRQL                       CurrentIrql;
616*c2c66affSColin Finck 
617*c2c66affSColin Finck     // first, __try to allocate out of the zone
618*c2c66affSColin Finck     KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
619*c2c66affSColin Finck     if (!ExIsFullZone(&(UDFGlobalData.ObjectNameZoneHeader))) {
620*c2c66affSColin Finck         // we have enough memory
621*c2c66affSColin Finck         PtrObjectName = (PtrUDFObjectName)ExAllocateFromZone(&(UDFGlobalData.ObjectNameZoneHeader));
622*c2c66affSColin Finck 
623*c2c66affSColin Finck         // release the spinlock
624*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
625*c2c66affSColin Finck     } else {
626*c2c66affSColin Finck         // release the spinlock
627*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
628*c2c66affSColin Finck 
629*c2c66affSColin Finck         // if we failed to obtain from the zone, get it directly from the VMM
630*c2c66affSColin Finck         PtrObjectName = (PtrUDFObjectName)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFObjectName)));
631*c2c66affSColin Finck         AllocatedFromZone = FALSE;
632*c2c66affSColin Finck     }
633*c2c66affSColin Finck 
634*c2c66affSColin Finck     if (!PtrObjectName) {
635*c2c66affSColin Finck         return NULL;
636*c2c66affSColin Finck     }
637*c2c66affSColin Finck 
638*c2c66affSColin Finck     // zero out the allocated memory block
639*c2c66affSColin Finck     RtlZeroMemory(PtrObjectName, UDFQuadAlign(sizeof(UDFObjectName)));
640*c2c66affSColin Finck 
641*c2c66affSColin Finck     // set up some fields ...
642*c2c66affSColin Finck     PtrObjectName->NodeIdentifier.NodeType  = UDF_NODE_TYPE_OBJECT_NAME;
643*c2c66affSColin Finck     PtrObjectName->NodeIdentifier.NodeSize  = UDFQuadAlign(sizeof(UDFObjectName));
644*c2c66affSColin Finck 
645*c2c66affSColin Finck 
646*c2c66affSColin Finck     if (!AllocatedFromZone) {
647*c2c66affSColin Finck         UDFSetFlag(PtrObjectName->ObjectNameFlags, UDF_OBJ_NAME_NOT_FROM_ZONE);
648*c2c66affSColin Finck     }
649*c2c66affSColin Finck 
650*c2c66affSColin Finck     return(PtrObjectName);
651*c2c66affSColin Finck } // end UDFAllocateObjectName()
652*c2c66affSColin Finck 
653*c2c66affSColin Finck 
654*c2c66affSColin Finck /*************************************************************************
655*c2c66affSColin Finck *
656*c2c66affSColin Finck * Function: UDFReleaseObjectName()
657*c2c66affSColin Finck *
658*c2c66affSColin Finck * Description:
659*c2c66affSColin Finck *   Deallocate a previously allocated structure.
660*c2c66affSColin Finck *
661*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
662*c2c66affSColin Finck *
663*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
664*c2c66affSColin Finck *
665*c2c66affSColin Finck * Return Value: None
666*c2c66affSColin Finck *
667*c2c66affSColin Finck *************************************************************************/
668*c2c66affSColin Finck VOID
669*c2c66affSColin Finck __fastcall
UDFReleaseObjectName(PtrUDFObjectName PtrObjectName)670*c2c66affSColin Finck UDFReleaseObjectName(
671*c2c66affSColin Finck     PtrUDFObjectName PtrObjectName)
672*c2c66affSColin Finck {
673*c2c66affSColin Finck     KIRQL            CurrentIrql;
674*c2c66affSColin Finck 
675*c2c66affSColin Finck     ASSERT(PtrObjectName);
676*c2c66affSColin Finck 
677*c2c66affSColin Finck     // give back memory either to the zone or to the VMM
678*c2c66affSColin Finck     if (!(PtrObjectName->ObjectNameFlags & UDF_OBJ_NAME_NOT_FROM_ZONE)) {
679*c2c66affSColin Finck         // back to the zone
680*c2c66affSColin Finck         KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
681*c2c66affSColin Finck         ExFreeToZone(&(UDFGlobalData.ObjectNameZoneHeader), PtrObjectName);
682*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
683*c2c66affSColin Finck     } else {
684*c2c66affSColin Finck         MyFreePool__(PtrObjectName);
685*c2c66affSColin Finck     }
686*c2c66affSColin Finck 
687*c2c66affSColin Finck     return;
688*c2c66affSColin Finck } // end UDFReleaseObjectName()
689*c2c66affSColin Finck 
690*c2c66affSColin Finck 
691*c2c66affSColin Finck /*************************************************************************
692*c2c66affSColin Finck *
693*c2c66affSColin Finck * Function: UDFAllocateCCB()
694*c2c66affSColin Finck *
695*c2c66affSColin Finck * Description:
696*c2c66affSColin Finck *   Allocate a new CCB structure to represent an open on-disk object.
697*c2c66affSColin Finck *   Also initialize the CCB structure to NULL.
698*c2c66affSColin Finck *
699*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
700*c2c66affSColin Finck *
701*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
702*c2c66affSColin Finck *
703*c2c66affSColin Finck * Return Value: A pointer to the CCB structure OR NULL.
704*c2c66affSColin Finck *
705*c2c66affSColin Finck *************************************************************************/
706*c2c66affSColin Finck PtrUDFCCB
UDFAllocateCCB(VOID)707*c2c66affSColin Finck UDFAllocateCCB(VOID)
708*c2c66affSColin Finck {
709*c2c66affSColin Finck     PtrUDFCCB                   Ccb = NULL;
710*c2c66affSColin Finck     BOOLEAN                     AllocatedFromZone = TRUE;
711*c2c66affSColin Finck     KIRQL                       CurrentIrql;
712*c2c66affSColin Finck 
713*c2c66affSColin Finck     // first, __try to allocate out of the zone
714*c2c66affSColin Finck     KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
715*c2c66affSColin Finck     if (!ExIsFullZone(&(UDFGlobalData.CCBZoneHeader))) {
716*c2c66affSColin Finck         // we have enough memory
717*c2c66affSColin Finck         Ccb = (PtrUDFCCB)ExAllocateFromZone(&(UDFGlobalData.CCBZoneHeader));
718*c2c66affSColin Finck 
719*c2c66affSColin Finck         // release the spinlock
720*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
721*c2c66affSColin Finck     } else {
722*c2c66affSColin Finck         // release the spinlock
723*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
724*c2c66affSColin Finck 
725*c2c66affSColin Finck         // if we failed to obtain from the zone, get it directly from the VMM
726*c2c66affSColin Finck         Ccb = (PtrUDFCCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFCCB)));
727*c2c66affSColin Finck         AllocatedFromZone = FALSE;
728*c2c66affSColin Finck //        UDFPrint(("    CCB allocated @%x\n",Ccb));
729*c2c66affSColin Finck     }
730*c2c66affSColin Finck 
731*c2c66affSColin Finck     if (!Ccb) {
732*c2c66affSColin Finck         return NULL;
733*c2c66affSColin Finck     }
734*c2c66affSColin Finck 
735*c2c66affSColin Finck     // zero out the allocated memory block
736*c2c66affSColin Finck     RtlZeroMemory(Ccb, UDFQuadAlign(sizeof(UDFCCB)));
737*c2c66affSColin Finck 
738*c2c66affSColin Finck     // set up some fields ...
739*c2c66affSColin Finck     Ccb->NodeIdentifier.NodeType = UDF_NODE_TYPE_CCB;
740*c2c66affSColin Finck     Ccb->NodeIdentifier.NodeSize = UDFQuadAlign(sizeof(UDFCCB));
741*c2c66affSColin Finck 
742*c2c66affSColin Finck 
743*c2c66affSColin Finck     if (!AllocatedFromZone) {
744*c2c66affSColin Finck         UDFSetFlag(Ccb->CCBFlags, UDF_CCB_NOT_FROM_ZONE);
745*c2c66affSColin Finck     }
746*c2c66affSColin Finck 
747*c2c66affSColin Finck     UDFPrint(("UDFAllocateCCB: %x\n", Ccb));
748*c2c66affSColin Finck     return(Ccb);
749*c2c66affSColin Finck } // end UDFAllocateCCB()
750*c2c66affSColin Finck 
751*c2c66affSColin Finck 
752*c2c66affSColin Finck /*************************************************************************
753*c2c66affSColin Finck *
754*c2c66affSColin Finck * Function: UDFReleaseCCB()
755*c2c66affSColin Finck *
756*c2c66affSColin Finck * Description:
757*c2c66affSColin Finck *   Deallocate a previously allocated structure.
758*c2c66affSColin Finck *
759*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
760*c2c66affSColin Finck *
761*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
762*c2c66affSColin Finck *
763*c2c66affSColin Finck * Return Value: None
764*c2c66affSColin Finck *
765*c2c66affSColin Finck *************************************************************************/
766*c2c66affSColin Finck VOID
767*c2c66affSColin Finck __fastcall
UDFReleaseCCB(PtrUDFCCB Ccb)768*c2c66affSColin Finck UDFReleaseCCB(
769*c2c66affSColin Finck     PtrUDFCCB Ccb
770*c2c66affSColin Finck     )
771*c2c66affSColin Finck {
772*c2c66affSColin Finck     KIRQL   CurrentIrql;
773*c2c66affSColin Finck 
774*c2c66affSColin Finck     ASSERT(Ccb);
775*c2c66affSColin Finck 
776*c2c66affSColin Finck     UDFPrint(("UDFReleaseCCB: %x\n", Ccb));
777*c2c66affSColin Finck     // give back memory either to the zone or to the VMM
778*c2c66affSColin Finck     if(!(Ccb->CCBFlags & UDF_CCB_NOT_FROM_ZONE)) {
779*c2c66affSColin Finck         // back to the zone
780*c2c66affSColin Finck         KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
781*c2c66affSColin Finck         ExFreeToZone(&(UDFGlobalData.CCBZoneHeader), Ccb);
782*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
783*c2c66affSColin Finck     } else {
784*c2c66affSColin Finck         MyFreePool__(Ccb);
785*c2c66affSColin Finck     }
786*c2c66affSColin Finck 
787*c2c66affSColin Finck     return;
788*c2c66affSColin Finck } // end UDFReleaseCCB()
789*c2c66affSColin Finck 
790*c2c66affSColin Finck /*
791*c2c66affSColin Finck   Function: UDFCleanupCCB()
792*c2c66affSColin Finck 
793*c2c66affSColin Finck   Description:
794*c2c66affSColin Finck     Cleanup and deallocate a previously allocated structure.
795*c2c66affSColin Finck 
796*c2c66affSColin Finck   Expected Interrupt Level (for execution) :
797*c2c66affSColin Finck 
798*c2c66affSColin Finck    IRQL_PASSIVE_LEVEL
799*c2c66affSColin Finck 
800*c2c66affSColin Finck   Return Value: None
801*c2c66affSColin Finck 
802*c2c66affSColin Finck */
803*c2c66affSColin Finck VOID
804*c2c66affSColin Finck __fastcall
UDFCleanUpCCB(PtrUDFCCB Ccb)805*c2c66affSColin Finck UDFCleanUpCCB(
806*c2c66affSColin Finck     PtrUDFCCB Ccb)
807*c2c66affSColin Finck {
808*c2c66affSColin Finck //    ASSERT(Ccb);
809*c2c66affSColin Finck     if(!Ccb) return; // probably, we havn't allocated it...
810*c2c66affSColin Finck     ASSERT(Ccb->NodeIdentifier.NodeType == UDF_NODE_TYPE_CCB);
811*c2c66affSColin Finck 
812*c2c66affSColin Finck     _SEH2_TRY {
813*c2c66affSColin Finck         if(Ccb->Fcb) {
814*c2c66affSColin Finck             UDFTouch(&(Ccb->Fcb->CcbListResource));
815*c2c66affSColin Finck             UDFAcquireResourceExclusive(&(Ccb->Fcb->CcbListResource),TRUE);
816*c2c66affSColin Finck             RemoveEntryList(&(Ccb->NextCCB));
817*c2c66affSColin Finck             UDFReleaseResource(&(Ccb->Fcb->CcbListResource));
818*c2c66affSColin Finck         } else {
819*c2c66affSColin Finck             BrutePoint();
820*c2c66affSColin Finck         }
821*c2c66affSColin Finck 
822*c2c66affSColin Finck         if (Ccb->DirectorySearchPattern) {
823*c2c66affSColin Finck             if (Ccb->DirectorySearchPattern->Buffer) {
824*c2c66affSColin Finck                 MyFreePool__(Ccb->DirectorySearchPattern->Buffer);
825*c2c66affSColin Finck                 Ccb->DirectorySearchPattern->Buffer = NULL;
826*c2c66affSColin Finck             }
827*c2c66affSColin Finck 
828*c2c66affSColin Finck             MyFreePool__(Ccb->DirectorySearchPattern);
829*c2c66affSColin Finck             Ccb->DirectorySearchPattern = NULL;
830*c2c66affSColin Finck         }
831*c2c66affSColin Finck 
832*c2c66affSColin Finck         UDFReleaseCCB(Ccb);
833*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
834*c2c66affSColin Finck         BrutePoint();
835*c2c66affSColin Finck     } _SEH2_END;
836*c2c66affSColin Finck } // end UDFCleanUpCCB()
837*c2c66affSColin Finck 
838*c2c66affSColin Finck /*************************************************************************
839*c2c66affSColin Finck *
840*c2c66affSColin Finck * Function: UDFAllocateFCB()
841*c2c66affSColin Finck *
842*c2c66affSColin Finck * Description:
843*c2c66affSColin Finck *   Allocate a new FCB structure to represent an open on-disk object.
844*c2c66affSColin Finck *   Also initialize the FCB structure to NULL.
845*c2c66affSColin Finck *
846*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
847*c2c66affSColin Finck *
848*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
849*c2c66affSColin Finck *
850*c2c66affSColin Finck * Return Value: A pointer to the FCB structure OR NULL.
851*c2c66affSColin Finck *
852*c2c66affSColin Finck *************************************************************************/
853*c2c66affSColin Finck PtrUDFFCB
UDFAllocateFCB(VOID)854*c2c66affSColin Finck UDFAllocateFCB(VOID)
855*c2c66affSColin Finck {
856*c2c66affSColin Finck     PtrUDFFCB                   Fcb = NULL;
857*c2c66affSColin Finck 
858*c2c66affSColin Finck     Fcb = (PtrUDFFCB)MyAllocatePool__(UDF_FCB_MT, UDFQuadAlign(sizeof(UDFFCB)));
859*c2c66affSColin Finck 
860*c2c66affSColin Finck     if (!Fcb) {
861*c2c66affSColin Finck         return NULL;
862*c2c66affSColin Finck     }
863*c2c66affSColin Finck 
864*c2c66affSColin Finck     // zero out the allocated memory block
865*c2c66affSColin Finck     RtlZeroMemory(Fcb, UDFQuadAlign(sizeof(UDFFCB)));
866*c2c66affSColin Finck 
867*c2c66affSColin Finck     // set up some fields ...
868*c2c66affSColin Finck     Fcb->NodeIdentifier.NodeType = UDF_NODE_TYPE_FCB;
869*c2c66affSColin Finck     Fcb->NodeIdentifier.NodeSize = UDFQuadAlign(sizeof(UDFFCB));
870*c2c66affSColin Finck 
871*c2c66affSColin Finck     UDFPrint(("UDFAllocateFCB: %x\n", Fcb));
872*c2c66affSColin Finck     return(Fcb);
873*c2c66affSColin Finck } // end UDFAllocateFCB()
874*c2c66affSColin Finck 
875*c2c66affSColin Finck 
876*c2c66affSColin Finck /*************************************************************************
877*c2c66affSColin Finck *
878*c2c66affSColin Finck * Function: UDFReleaseFCB()
879*c2c66affSColin Finck *
880*c2c66affSColin Finck * Description:
881*c2c66affSColin Finck *   Deallocate a previously allocated structure.
882*c2c66affSColin Finck *
883*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
884*c2c66affSColin Finck *
885*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
886*c2c66affSColin Finck *
887*c2c66affSColin Finck * Return Value: None
888*c2c66affSColin Finck *
889*c2c66affSColin Finck *************************************************************************/
890*c2c66affSColin Finck /*VOID
891*c2c66affSColin Finck UDFReleaseFCB(
892*c2c66affSColin Finck     PtrUDFFCB Fcb
893*c2c66affSColin Finck     )
894*c2c66affSColin Finck {
895*c2c66affSColin Finck     ASSERT(Fcb);
896*c2c66affSColin Finck 
897*c2c66affSColin Finck     MyFreePool__(Fcb);
898*c2c66affSColin Finck 
899*c2c66affSColin Finck     return;
900*c2c66affSColin Finck }*/
901*c2c66affSColin Finck 
902*c2c66affSColin Finck /*************************************************************************
903*c2c66affSColin Finck *
904*c2c66affSColin Finck *
905*c2c66affSColin Finck *************************************************************************/
906*c2c66affSColin Finck VOID
907*c2c66affSColin Finck __fastcall
UDFCleanUpFCB(PtrUDFFCB Fcb)908*c2c66affSColin Finck UDFCleanUpFCB(
909*c2c66affSColin Finck     PtrUDFFCB Fcb
910*c2c66affSColin Finck     )
911*c2c66affSColin Finck {
912*c2c66affSColin Finck     UDFPrint(("UDFCleanUpFCB: %x\n", Fcb));
913*c2c66affSColin Finck     if(!Fcb) return;
914*c2c66affSColin Finck 
915*c2c66affSColin Finck     ASSERT(Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB);
916*c2c66affSColin Finck 
917*c2c66affSColin Finck     _SEH2_TRY {
918*c2c66affSColin Finck         // Deinitialize FCBName field
919*c2c66affSColin Finck         if (Fcb->FCBName) {
920*c2c66affSColin Finck             if(Fcb->FCBName->ObjectName.Buffer) {
921*c2c66affSColin Finck                 MyFreePool__(Fcb->FCBName->ObjectName.Buffer);
922*c2c66affSColin Finck                 Fcb->FCBName->ObjectName.Buffer = NULL;
923*c2c66affSColin Finck #ifdef UDF_DBG
924*c2c66affSColin Finck                 Fcb->FCBName->ObjectName.Length =
925*c2c66affSColin Finck                 Fcb->FCBName->ObjectName.MaximumLength = 0;
926*c2c66affSColin Finck #endif
927*c2c66affSColin Finck             }
928*c2c66affSColin Finck #ifdef UDF_DBG
929*c2c66affSColin Finck             else {
930*c2c66affSColin Finck                 UDFPrint(("UDF: Fcb has invalid FCBName Buffer\n"));
931*c2c66affSColin Finck                 BrutePoint();
932*c2c66affSColin Finck             }
933*c2c66affSColin Finck #endif
934*c2c66affSColin Finck             UDFReleaseObjectName(Fcb->FCBName);
935*c2c66affSColin Finck             Fcb->FCBName = NULL;
936*c2c66affSColin Finck         }
937*c2c66affSColin Finck #ifdef UDF_DBG
938*c2c66affSColin Finck         else {
939*c2c66affSColin Finck             UDFPrint(("UDF: Fcb has invalid FCBName field\n"));
940*c2c66affSColin Finck             BrutePoint();
941*c2c66affSColin Finck         }
942*c2c66affSColin Finck #endif
943*c2c66affSColin Finck 
944*c2c66affSColin Finck 
945*c2c66affSColin Finck         // begin transaction {
946*c2c66affSColin Finck         UDFTouch(&(Fcb->Vcb->FcbListResource));
947*c2c66affSColin Finck         UDFAcquireResourceExclusive(&(Fcb->Vcb->FcbListResource), TRUE);
948*c2c66affSColin Finck         // Remove this FCB from list of all FCB in VCB
949*c2c66affSColin Finck         RemoveEntryList(&(Fcb->NextFCB));
950*c2c66affSColin Finck         UDFReleaseResource(&(Fcb->Vcb->FcbListResource));
951*c2c66affSColin Finck         // } end transaction
952*c2c66affSColin Finck 
953*c2c66affSColin Finck         if(Fcb->FCBFlags & UDF_FCB_INITIALIZED_CCB_LIST_RESOURCE)
954*c2c66affSColin Finck             UDFDeleteResource(&(Fcb->CcbListResource));
955*c2c66affSColin Finck 
956*c2c66affSColin Finck         // Free memory
957*c2c66affSColin Finck         UDFReleaseFCB(Fcb);
958*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
959*c2c66affSColin Finck         BrutePoint();
960*c2c66affSColin Finck     } _SEH2_END;
961*c2c66affSColin Finck } // end UDFCleanUpFCB()
962*c2c66affSColin Finck 
963*c2c66affSColin Finck #ifdef UDF_DBG
964*c2c66affSColin Finck ULONG IrpContextCounter = 0;
965*c2c66affSColin Finck #endif //UDF_DBG
966*c2c66affSColin Finck 
967*c2c66affSColin Finck /*************************************************************************
968*c2c66affSColin Finck *
969*c2c66affSColin Finck * Function: UDFAllocateIrpContext()
970*c2c66affSColin Finck *
971*c2c66affSColin Finck * Description:
972*c2c66affSColin Finck *   The UDF FSD creates an IRP context for each request received. This
973*c2c66affSColin Finck *   routine simply allocates (and initializes to NULL) a UDFIrpContext
974*c2c66affSColin Finck *   structure.
975*c2c66affSColin Finck *   Most of the fields in the context structure are then initialized here.
976*c2c66affSColin Finck *
977*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
978*c2c66affSColin Finck *
979*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
980*c2c66affSColin Finck *
981*c2c66affSColin Finck * Return Value: A pointer to the IrpContext structure OR NULL.
982*c2c66affSColin Finck *
983*c2c66affSColin Finck *************************************************************************/
984*c2c66affSColin Finck PtrUDFIrpContext
UDFAllocateIrpContext(PIRP Irp,PDEVICE_OBJECT PtrTargetDeviceObject)985*c2c66affSColin Finck UDFAllocateIrpContext(
986*c2c66affSColin Finck     PIRP           Irp,
987*c2c66affSColin Finck     PDEVICE_OBJECT PtrTargetDeviceObject
988*c2c66affSColin Finck     )
989*c2c66affSColin Finck {
990*c2c66affSColin Finck     PtrUDFIrpContext            PtrIrpContext = NULL;
991*c2c66affSColin Finck     BOOLEAN                     AllocatedFromZone = TRUE;
992*c2c66affSColin Finck     KIRQL                       CurrentIrql;
993*c2c66affSColin Finck     PIO_STACK_LOCATION          IrpSp = NULL;
994*c2c66affSColin Finck 
995*c2c66affSColin Finck     // first, __try to allocate out of the zone
996*c2c66affSColin Finck     KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
997*c2c66affSColin Finck     if (!ExIsFullZone(&(UDFGlobalData.IrpContextZoneHeader))) {
998*c2c66affSColin Finck         // we have enough memory
999*c2c66affSColin Finck         PtrIrpContext = (PtrUDFIrpContext)ExAllocateFromZone(&(UDFGlobalData.IrpContextZoneHeader));
1000*c2c66affSColin Finck 
1001*c2c66affSColin Finck         // release the spinlock
1002*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
1003*c2c66affSColin Finck     } else {
1004*c2c66affSColin Finck         // release the spinlock
1005*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
1006*c2c66affSColin Finck 
1007*c2c66affSColin Finck         // if we failed to obtain from the zone, get it directly from the VMM
1008*c2c66affSColin Finck         PtrIrpContext = (PtrUDFIrpContext)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFIrpContext)));
1009*c2c66affSColin Finck         AllocatedFromZone = FALSE;
1010*c2c66affSColin Finck     }
1011*c2c66affSColin Finck 
1012*c2c66affSColin Finck     // if we could not obtain the required memory, bug-check.
1013*c2c66affSColin Finck     //  Do NOT do this in your commercial driver, instead handle    the error gracefully ...
1014*c2c66affSColin Finck     if (!PtrIrpContext) {
1015*c2c66affSColin Finck         return NULL;
1016*c2c66affSColin Finck     }
1017*c2c66affSColin Finck 
1018*c2c66affSColin Finck #ifdef UDF_DBG
1019*c2c66affSColin Finck     IrpContextCounter++;
1020*c2c66affSColin Finck #endif //UDF_DBG
1021*c2c66affSColin Finck 
1022*c2c66affSColin Finck     // zero out the allocated memory block
1023*c2c66affSColin Finck     RtlZeroMemory(PtrIrpContext, UDFQuadAlign(sizeof(UDFIrpContext)));
1024*c2c66affSColin Finck 
1025*c2c66affSColin Finck     // set up some fields ...
1026*c2c66affSColin Finck     PtrIrpContext->NodeIdentifier.NodeType  = UDF_NODE_TYPE_IRP_CONTEXT;
1027*c2c66affSColin Finck     PtrIrpContext->NodeIdentifier.NodeSize  = UDFQuadAlign(sizeof(UDFIrpContext));
1028*c2c66affSColin Finck 
1029*c2c66affSColin Finck 
1030*c2c66affSColin Finck     PtrIrpContext->Irp = Irp;
1031*c2c66affSColin Finck     PtrIrpContext->TargetDeviceObject = PtrTargetDeviceObject;
1032*c2c66affSColin Finck 
1033*c2c66affSColin Finck     // copy over some fields from the IRP and set appropriate flag values
1034*c2c66affSColin Finck     if (Irp) {
1035*c2c66affSColin Finck         IrpSp = IoGetCurrentIrpStackLocation(Irp);
1036*c2c66affSColin Finck         ASSERT(IrpSp);
1037*c2c66affSColin Finck 
1038*c2c66affSColin Finck         PtrIrpContext->MajorFunction = IrpSp->MajorFunction;
1039*c2c66affSColin Finck         PtrIrpContext->MinorFunction = IrpSp->MinorFunction;
1040*c2c66affSColin Finck 
1041*c2c66affSColin Finck         // Often, a FSD cannot honor a request for asynchronous processing
1042*c2c66affSColin Finck         // of certain critical requests. For example, a "close" request on
1043*c2c66affSColin Finck         // a file object can typically never be deferred. Therefore, do not
1044*c2c66affSColin Finck         // be surprised if sometimes our FSD (just like all other FSD
1045*c2c66affSColin Finck         // implementations on the Windows NT system) has to override the flag
1046*c2c66affSColin Finck         // below.
1047*c2c66affSColin Finck         if (IrpSp->FileObject == NULL) {
1048*c2c66affSColin Finck             PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_CAN_BLOCK;
1049*c2c66affSColin Finck         } else {
1050*c2c66affSColin Finck             if (IoIsOperationSynchronous(Irp)) {
1051*c2c66affSColin Finck                 PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_CAN_BLOCK;
1052*c2c66affSColin Finck             }
1053*c2c66affSColin Finck         }
1054*c2c66affSColin Finck     }
1055*c2c66affSColin Finck 
1056*c2c66affSColin Finck     if (!AllocatedFromZone) {
1057*c2c66affSColin Finck         UDFSetFlag(PtrIrpContext->IrpContextFlags, UDF_IRP_CONTEXT_NOT_FROM_ZONE);
1058*c2c66affSColin Finck     }
1059*c2c66affSColin Finck 
1060*c2c66affSColin Finck     // Are we top-level ? This information is used by the dispatching code
1061*c2c66affSColin Finck     // later (and also by the FSD dispatch routine)
1062*c2c66affSColin Finck     if (IoGetTopLevelIrp() != Irp) {
1063*c2c66affSColin Finck         // We are not top-level. Note this fact in the context structure
1064*c2c66affSColin Finck         UDFSetFlag(PtrIrpContext->IrpContextFlags, UDF_IRP_CONTEXT_NOT_TOP_LEVEL);
1065*c2c66affSColin Finck     }
1066*c2c66affSColin Finck 
1067*c2c66affSColin Finck     return(PtrIrpContext);
1068*c2c66affSColin Finck } // end UDFAllocateIrpContext()
1069*c2c66affSColin Finck 
1070*c2c66affSColin Finck 
1071*c2c66affSColin Finck /*************************************************************************
1072*c2c66affSColin Finck *
1073*c2c66affSColin Finck * Function: UDFReleaseIrpContext()
1074*c2c66affSColin Finck *
1075*c2c66affSColin Finck * Description:
1076*c2c66affSColin Finck *   Deallocate a previously allocated structure.
1077*c2c66affSColin Finck *
1078*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1079*c2c66affSColin Finck *
1080*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
1081*c2c66affSColin Finck *
1082*c2c66affSColin Finck * Return Value: None
1083*c2c66affSColin Finck *
1084*c2c66affSColin Finck *************************************************************************/
1085*c2c66affSColin Finck VOID
UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)1086*c2c66affSColin Finck UDFReleaseIrpContext(
1087*c2c66affSColin Finck     PtrUDFIrpContext    PtrIrpContext)
1088*c2c66affSColin Finck {
1089*c2c66affSColin Finck     if(!PtrIrpContext) return;
1090*c2c66affSColin Finck //    ASSERT(PtrIrpContext);
1091*c2c66affSColin Finck 
1092*c2c66affSColin Finck #ifdef UDF_DBG
1093*c2c66affSColin Finck     IrpContextCounter--;
1094*c2c66affSColin Finck #endif //UDF_DBG
1095*c2c66affSColin Finck 
1096*c2c66affSColin Finck     // give back memory either to the zone or to the VMM
1097*c2c66affSColin Finck     if (!(PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_NOT_FROM_ZONE)) {
1098*c2c66affSColin Finck         // back to the zone
1099*c2c66affSColin Finck         KIRQL                           CurrentIrql;
1100*c2c66affSColin Finck 
1101*c2c66affSColin Finck         KeAcquireSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), &CurrentIrql);
1102*c2c66affSColin Finck         ExFreeToZone(&(UDFGlobalData.IrpContextZoneHeader), PtrIrpContext);
1103*c2c66affSColin Finck         KeReleaseSpinLock(&(UDFGlobalData.ZoneAllocationSpinLock), CurrentIrql);
1104*c2c66affSColin Finck     } else {
1105*c2c66affSColin Finck         MyFreePool__(PtrIrpContext);
1106*c2c66affSColin Finck     }
1107*c2c66affSColin Finck 
1108*c2c66affSColin Finck     return;
1109*c2c66affSColin Finck } // end UDFReleaseIrpContext()
1110*c2c66affSColin Finck 
1111*c2c66affSColin Finck 
1112*c2c66affSColin Finck /*************************************************************************
1113*c2c66affSColin Finck *
1114*c2c66affSColin Finck * Function: UDFPostRequest()
1115*c2c66affSColin Finck *
1116*c2c66affSColin Finck * Description:
1117*c2c66affSColin Finck *   Queue up a request for deferred processing (in the context of a system
1118*c2c66affSColin Finck *   worker thread). The caller must have locked the user buffer (if required)
1119*c2c66affSColin Finck *
1120*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1121*c2c66affSColin Finck *
1122*c2c66affSColin Finck *  IRQL_PASSIVE_LEVEL
1123*c2c66affSColin Finck *
1124*c2c66affSColin Finck * Return Value: STATUS_PENDING
1125*c2c66affSColin Finck *
1126*c2c66affSColin Finck *************************************************************************/
1127*c2c66affSColin Finck NTSTATUS
UDFPostRequest(IN PtrUDFIrpContext PtrIrpContext,IN PIRP Irp)1128*c2c66affSColin Finck UDFPostRequest(
1129*c2c66affSColin Finck     IN PtrUDFIrpContext PtrIrpContext,
1130*c2c66affSColin Finck     IN PIRP             Irp
1131*c2c66affSColin Finck     )
1132*c2c66affSColin Finck {
1133*c2c66affSColin Finck     KIRQL SavedIrql;
1134*c2c66affSColin Finck //    PIO_STACK_LOCATION IrpSp;
1135*c2c66affSColin Finck     PVCB Vcb;
1136*c2c66affSColin Finck 
1137*c2c66affSColin Finck //    IrpSp = IoGetCurrentIrpStackLocation(Irp);
1138*c2c66affSColin Finck 
1139*c2c66affSColin Finck /*
1140*c2c66affSColin Finck     if(Vcb->StopOverflowQueue) {
1141*c2c66affSColin Finck         if(Irp) {
1142*c2c66affSColin Finck             Irp->IoStatus.Status = STATUS_WRONG_VOLUME;
1143*c2c66affSColin Finck             Irp->IoStatus.Information = 0;
1144*c2c66affSColin Finck             IoCompleteRequest(Irp, IO_DISK_INCREMENT);
1145*c2c66affSColin Finck         }
1146*c2c66affSColin Finck         UDFReleaseIrpContext(PtrIrpContext);
1147*c2c66affSColin Finck         return STATUS_WRONG_VOLUME;
1148*c2c66affSColin Finck     }
1149*c2c66affSColin Finck */
1150*c2c66affSColin Finck     // mark the IRP pending if this is not double post
1151*c2c66affSColin Finck     if(Irp)
1152*c2c66affSColin Finck         IoMarkIrpPending(Irp);
1153*c2c66affSColin Finck 
1154*c2c66affSColin Finck     Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
1155*c2c66affSColin Finck     KeAcquireSpinLock(&(Vcb->OverflowQueueSpinLock), &SavedIrql);
1156*c2c66affSColin Finck 
1157*c2c66affSColin Finck     if ( Vcb->PostedRequestCount > FSP_PER_DEVICE_THRESHOLD) {
1158*c2c66affSColin Finck 
1159*c2c66affSColin Finck         //  We cannot currently respond to this IRP so we'll just enqueue it
1160*c2c66affSColin Finck         //  to the overflow queue on the volume.
1161*c2c66affSColin Finck         //  Note: we just reuse LIST_ITEM field inside WorkQueueItem, this
1162*c2c66affSColin Finck         //  doesn't matter to regular processing of WorkItems.
1163*c2c66affSColin Finck         InsertTailList( &(Vcb->OverflowQueue),
1164*c2c66affSColin Finck                         &(PtrIrpContext->WorkQueueItem.List) );
1165*c2c66affSColin Finck         Vcb->OverflowQueueCount++;
1166*c2c66affSColin Finck         KeReleaseSpinLock( &(Vcb->OverflowQueueSpinLock), SavedIrql );
1167*c2c66affSColin Finck 
1168*c2c66affSColin Finck     } else {
1169*c2c66affSColin Finck 
1170*c2c66affSColin Finck         //  We are going to send this Irp to an ex worker thread so up
1171*c2c66affSColin Finck         //  the count.
1172*c2c66affSColin Finck         Vcb->PostedRequestCount++;
1173*c2c66affSColin Finck 
1174*c2c66affSColin Finck         KeReleaseSpinLock( &(Vcb->OverflowQueueSpinLock), SavedIrql );
1175*c2c66affSColin Finck 
1176*c2c66affSColin Finck         // queue up the request
1177*c2c66affSColin Finck         ExInitializeWorkItem(&(PtrIrpContext->WorkQueueItem), UDFCommonDispatch, PtrIrpContext);
1178*c2c66affSColin Finck 
1179*c2c66affSColin Finck         ExQueueWorkItem(&(PtrIrpContext->WorkQueueItem), CriticalWorkQueue);
1180*c2c66affSColin Finck     //    ExQueueWorkItem(&(PtrIrpContext->WorkQueueItem), DelayedWorkQueue);
1181*c2c66affSColin Finck 
1182*c2c66affSColin Finck     }
1183*c2c66affSColin Finck 
1184*c2c66affSColin Finck     // return status pending
1185*c2c66affSColin Finck     return STATUS_PENDING;
1186*c2c66affSColin Finck } // end UDFPostRequest()
1187*c2c66affSColin Finck 
1188*c2c66affSColin Finck 
1189*c2c66affSColin Finck /*************************************************************************
1190*c2c66affSColin Finck *
1191*c2c66affSColin Finck * Function: UDFCommonDispatch()
1192*c2c66affSColin Finck *
1193*c2c66affSColin Finck * Description:
1194*c2c66affSColin Finck *   The common dispatch routine invoked in the context of a system worker
1195*c2c66affSColin Finck *   thread. All we do here is pretty much case off the major function
1196*c2c66affSColin Finck *   code and invoke the appropriate FSD dispatch routine for further
1197*c2c66affSColin Finck *   processing.
1198*c2c66affSColin Finck *
1199*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1200*c2c66affSColin Finck *
1201*c2c66affSColin Finck *   IRQL PASSIVE_LEVEL
1202*c2c66affSColin Finck *
1203*c2c66affSColin Finck * Return Value: None
1204*c2c66affSColin Finck *
1205*c2c66affSColin Finck *************************************************************************/
1206*c2c66affSColin Finck VOID
1207*c2c66affSColin Finck NTAPI
UDFCommonDispatch(IN PVOID Context)1208*c2c66affSColin Finck UDFCommonDispatch(
1209*c2c66affSColin Finck     IN PVOID Context   // actually is a pointer to IRPContext structure
1210*c2c66affSColin Finck     )
1211*c2c66affSColin Finck {
1212*c2c66affSColin Finck     NTSTATUS         RC = STATUS_SUCCESS;
1213*c2c66affSColin Finck     PtrUDFIrpContext PtrIrpContext = NULL;
1214*c2c66affSColin Finck     PIRP             Irp = NULL;
1215*c2c66affSColin Finck     PVCB             Vcb;
1216*c2c66affSColin Finck     KIRQL            SavedIrql;
1217*c2c66affSColin Finck     PLIST_ENTRY      Entry;
1218*c2c66affSColin Finck     BOOLEAN          SpinLock = FALSE;
1219*c2c66affSColin Finck 
1220*c2c66affSColin Finck     // The context must be a pointer to an IrpContext structure
1221*c2c66affSColin Finck     PtrIrpContext = (PtrUDFIrpContext)Context;
1222*c2c66affSColin Finck 
1223*c2c66affSColin Finck     // Assert that the Context is legitimate
1224*c2c66affSColin Finck     if ( !PtrIrpContext ||
1225*c2c66affSColin Finck          (PtrIrpContext->NodeIdentifier.NodeType != UDF_NODE_TYPE_IRP_CONTEXT) ||
1226*c2c66affSColin Finck          (PtrIrpContext->NodeIdentifier.NodeSize != UDFQuadAlign(sizeof(UDFIrpContext))) /*||
1227*c2c66affSColin Finck         !(PtrIrpContext->Irp)*/) {
1228*c2c66affSColin Finck         UDFPrint(("    Invalid Context\n"));
1229*c2c66affSColin Finck         BrutePoint();
1230*c2c66affSColin Finck         return;
1231*c2c66affSColin Finck     }
1232*c2c66affSColin Finck 
1233*c2c66affSColin Finck     Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
1234*c2c66affSColin Finck     ASSERT(Vcb);
1235*c2c66affSColin Finck 
1236*c2c66affSColin Finck     UDFPrint(("  *** Thr: %x  ThCnt: %x  QCnt: %x  Started!\n", PsGetCurrentThread(), Vcb->PostedRequestCount, Vcb->OverflowQueueCount));
1237*c2c66affSColin Finck 
1238*c2c66affSColin Finck     while(TRUE) {
1239*c2c66affSColin Finck 
1240*c2c66affSColin Finck         UDFPrint(("    Next IRP\n"));
1241*c2c66affSColin Finck         FsRtlEnterFileSystem();
1242*c2c66affSColin Finck 
1243*c2c66affSColin Finck         //  Get a pointer to the IRP structure
1244*c2c66affSColin Finck         // in some cases we can get Zero pointer to Irp
1245*c2c66affSColin Finck         Irp = PtrIrpContext->Irp;
1246*c2c66affSColin Finck         // Now, check if the FSD was top level when the IRP was originally invoked
1247*c2c66affSColin Finck         // and set the thread context (for the worker thread) appropriately
1248*c2c66affSColin Finck         if (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_NOT_TOP_LEVEL) {
1249*c2c66affSColin Finck             // The FSD is not top level for the original request
1250*c2c66affSColin Finck             // Set a constant value in TLS to reflect this fact
1251*c2c66affSColin Finck             IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
1252*c2c66affSColin Finck         } else {
1253*c2c66affSColin Finck             IoSetTopLevelIrp(Irp);
1254*c2c66affSColin Finck         }
1255*c2c66affSColin Finck 
1256*c2c66affSColin Finck         // Since the FSD routine will now be invoked in the context of this worker
1257*c2c66affSColin Finck         // thread, we should inform the FSD that it is perfectly OK to block in
1258*c2c66affSColin Finck         // the context of this thread
1259*c2c66affSColin Finck         PtrIrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_CAN_BLOCK;
1260*c2c66affSColin Finck 
1261*c2c66affSColin Finck         _SEH2_TRY {
1262*c2c66affSColin Finck 
1263*c2c66affSColin Finck             // Pre-processing has been completed; check the Major Function code value
1264*c2c66affSColin Finck             // either in the IrpContext (copied from the IRP), or directly from the
1265*c2c66affSColin Finck             //  IRP itself (we will need a pointer to the stack location to do that),
1266*c2c66affSColin Finck             //  Then, switch based on the value on the Major Function code
1267*c2c66affSColin Finck             UDFPrint(("  *** MJ: %x, Thr: %x\n", PtrIrpContext->MajorFunction, PsGetCurrentThread()));
1268*c2c66affSColin Finck             switch (PtrIrpContext->MajorFunction) {
1269*c2c66affSColin Finck             case IRP_MJ_CREATE:
1270*c2c66affSColin Finck                 // Invoke the common create routine
1271*c2c66affSColin Finck                 RC = UDFCommonCreate(PtrIrpContext, Irp);
1272*c2c66affSColin Finck                 break;
1273*c2c66affSColin Finck             case IRP_MJ_READ:
1274*c2c66affSColin Finck                 // Invoke the common read routine
1275*c2c66affSColin Finck                 RC = UDFCommonRead(PtrIrpContext, Irp);
1276*c2c66affSColin Finck                 break;
1277*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1278*c2c66affSColin Finck             case IRP_MJ_WRITE:
1279*c2c66affSColin Finck                 // Invoke the common write routine
1280*c2c66affSColin Finck                 RC = UDFCommonWrite(PtrIrpContext, Irp);
1281*c2c66affSColin Finck                 break;
1282*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1283*c2c66affSColin Finck             case IRP_MJ_CLEANUP:
1284*c2c66affSColin Finck                 // Invoke the common cleanup routine
1285*c2c66affSColin Finck                 RC = UDFCommonCleanup(PtrIrpContext, Irp);
1286*c2c66affSColin Finck                 break;
1287*c2c66affSColin Finck             case IRP_MJ_CLOSE:
1288*c2c66affSColin Finck                 // Invoke the common close routine
1289*c2c66affSColin Finck                 RC = UDFCommonClose(PtrIrpContext, Irp);
1290*c2c66affSColin Finck                 break;
1291*c2c66affSColin Finck             case IRP_MJ_DIRECTORY_CONTROL:
1292*c2c66affSColin Finck                 // Invoke the common directory control routine
1293*c2c66affSColin Finck                 RC = UDFCommonDirControl(PtrIrpContext, Irp);
1294*c2c66affSColin Finck                 break;
1295*c2c66affSColin Finck             case IRP_MJ_QUERY_INFORMATION:
1296*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1297*c2c66affSColin Finck             case IRP_MJ_SET_INFORMATION:
1298*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1299*c2c66affSColin Finck                 // Invoke the common query/set information routine
1300*c2c66affSColin Finck                 RC = UDFCommonFileInfo(PtrIrpContext, Irp);
1301*c2c66affSColin Finck                 break;
1302*c2c66affSColin Finck             case IRP_MJ_QUERY_VOLUME_INFORMATION:
1303*c2c66affSColin Finck                 // Invoke the common query volume routine
1304*c2c66affSColin Finck                 RC = UDFCommonQueryVolInfo(PtrIrpContext, Irp);
1305*c2c66affSColin Finck                 break;
1306*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1307*c2c66affSColin Finck             case IRP_MJ_SET_VOLUME_INFORMATION:
1308*c2c66affSColin Finck                 // Invoke the common query volume routine
1309*c2c66affSColin Finck                 RC = UDFCommonSetVolInfo(PtrIrpContext, Irp);
1310*c2c66affSColin Finck                 break;
1311*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1312*c2c66affSColin Finck #ifdef UDF_HANDLE_EAS
1313*c2c66affSColin Finck /*            case IRP_MJ_QUERY_EA:
1314*c2c66affSColin Finck                 // Invoke the common query EAs routine
1315*c2c66affSColin Finck                 RC = UDFCommonGetExtendedAttr(PtrIrpContext, Irp);
1316*c2c66affSColin Finck                 break;
1317*c2c66affSColin Finck             case IRP_MJ_SET_EA:
1318*c2c66affSColin Finck                 // Invoke the common set EAs routine
1319*c2c66affSColin Finck                 RC = UDFCommonSetExtendedAttr(PtrIrpContext, Irp);
1320*c2c66affSColin Finck                 break;*/
1321*c2c66affSColin Finck #endif // UDF_HANDLE_EAS
1322*c2c66affSColin Finck #ifdef UDF_ENABLE_SECURITY
1323*c2c66affSColin Finck             case IRP_MJ_QUERY_SECURITY:
1324*c2c66affSColin Finck                 // Invoke the common query Security routine
1325*c2c66affSColin Finck                 RC = UDFCommonGetSecurity(PtrIrpContext, Irp);
1326*c2c66affSColin Finck                 break;
1327*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1328*c2c66affSColin Finck             case IRP_MJ_SET_SECURITY:
1329*c2c66affSColin Finck                 // Invoke the common set Security routine
1330*c2c66affSColin Finck                 RC = UDFCommonSetSecurity(PtrIrpContext, Irp);
1331*c2c66affSColin Finck                 break;
1332*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1333*c2c66affSColin Finck #endif // UDF_ENABLE_SECURITY
1334*c2c66affSColin Finck             // Continue with the remaining possible dispatch routines below ...
1335*c2c66affSColin Finck             default:
1336*c2c66affSColin Finck                 UDFPrint(("  unhandled *** MJ: %x, Thr: %x\n", PtrIrpContext->MajorFunction, PsGetCurrentThread()));
1337*c2c66affSColin Finck                 // This is the case where we have an invalid major function
1338*c2c66affSColin Finck                 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1339*c2c66affSColin Finck                 Irp->IoStatus.Information = 0;
1340*c2c66affSColin Finck 
1341*c2c66affSColin Finck                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1342*c2c66affSColin Finck                 // Free up the Irp Context
1343*c2c66affSColin Finck                 UDFReleaseIrpContext(PtrIrpContext);
1344*c2c66affSColin Finck                 break;
1345*c2c66affSColin Finck             }
1346*c2c66affSColin Finck 
1347*c2c66affSColin Finck             // Note: PtrIrpContext is invalid here
1348*c2c66affSColin Finck             UDFPrint(("  *** Thr: %x  Done!\n", PsGetCurrentThread()));
1349*c2c66affSColin Finck 
1350*c2c66affSColin Finck         } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
1351*c2c66affSColin Finck 
1352*c2c66affSColin Finck             RC = UDFExceptionHandler(PtrIrpContext, Irp);
1353*c2c66affSColin Finck 
1354*c2c66affSColin Finck             UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
1355*c2c66affSColin Finck         }  _SEH2_END;
1356*c2c66affSColin Finck 
1357*c2c66affSColin Finck         // Enable preemption
1358*c2c66affSColin Finck         FsRtlExitFileSystem();
1359*c2c66affSColin Finck 
1360*c2c66affSColin Finck         // Ensure that the "top-level" field is cleared
1361*c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
1362*c2c66affSColin Finck 
1363*c2c66affSColin Finck         //  If there are any entries on this volume's overflow queue, service
1364*c2c66affSColin Finck         //  them.
1365*c2c66affSColin Finck         if(!Vcb) {
1366*c2c66affSColin Finck             BrutePoint();
1367*c2c66affSColin Finck             break;
1368*c2c66affSColin Finck         }
1369*c2c66affSColin Finck 
1370*c2c66affSColin Finck         KeAcquireSpinLock(&(Vcb->OverflowQueueSpinLock), &SavedIrql);
1371*c2c66affSColin Finck         SpinLock = TRUE;
1372*c2c66affSColin Finck         if(!Vcb->OverflowQueueCount)
1373*c2c66affSColin Finck             break;
1374*c2c66affSColin Finck 
1375*c2c66affSColin Finck         Vcb->OverflowQueueCount--;
1376*c2c66affSColin Finck         Entry = RemoveHeadList(&Vcb->OverflowQueue);
1377*c2c66affSColin Finck         KeReleaseSpinLock(&(Vcb->OverflowQueueSpinLock), SavedIrql);
1378*c2c66affSColin Finck         SpinLock = FALSE;
1379*c2c66affSColin Finck 
1380*c2c66affSColin Finck         PtrIrpContext = CONTAINING_RECORD( Entry,
1381*c2c66affSColin Finck                                         UDFIrpContext,
1382*c2c66affSColin Finck                                         WorkQueueItem.List );
1383*c2c66affSColin Finck     }
1384*c2c66affSColin Finck 
1385*c2c66affSColin Finck     if(!SpinLock)
1386*c2c66affSColin Finck         KeAcquireSpinLock(&(Vcb->OverflowQueueSpinLock), &SavedIrql);
1387*c2c66affSColin Finck     Vcb->PostedRequestCount--;
1388*c2c66affSColin Finck     KeReleaseSpinLock(&(Vcb->OverflowQueueSpinLock), SavedIrql);
1389*c2c66affSColin Finck 
1390*c2c66affSColin Finck     UDFPrint(("  *** Thr: %x  ThCnt: %x  QCnt: %x  Terminated!\n", PsGetCurrentThread(), Vcb->PostedRequestCount, Vcb->OverflowQueueCount));
1391*c2c66affSColin Finck 
1392*c2c66affSColin Finck     return;
1393*c2c66affSColin Finck } // end UDFCommonDispatch()
1394*c2c66affSColin Finck 
1395*c2c66affSColin Finck 
1396*c2c66affSColin Finck /*************************************************************************
1397*c2c66affSColin Finck *
1398*c2c66affSColin Finck * Function: UDFInitializeVCB()
1399*c2c66affSColin Finck *
1400*c2c66affSColin Finck * Description:
1401*c2c66affSColin Finck *   Perform the initialization for a VCB structure.
1402*c2c66affSColin Finck *
1403*c2c66affSColin Finck * Expected Interrupt Level (for execution) :
1404*c2c66affSColin Finck *
1405*c2c66affSColin Finck *   IRQL PASSIVE_LEVEL
1406*c2c66affSColin Finck *
1407*c2c66affSColin Finck * Return Value: status
1408*c2c66affSColin Finck *
1409*c2c66affSColin Finck *************************************************************************/
1410*c2c66affSColin Finck NTSTATUS
UDFInitializeVCB(IN PDEVICE_OBJECT PtrVolumeDeviceObject,IN PDEVICE_OBJECT PtrTargetDeviceObject,IN PVPB PtrVPB)1411*c2c66affSColin Finck UDFInitializeVCB(
1412*c2c66affSColin Finck     IN PDEVICE_OBJECT PtrVolumeDeviceObject,
1413*c2c66affSColin Finck     IN PDEVICE_OBJECT PtrTargetDeviceObject,
1414*c2c66affSColin Finck     IN PVPB           PtrVPB
1415*c2c66affSColin Finck     )
1416*c2c66affSColin Finck {
1417*c2c66affSColin Finck     NTSTATUS RC = STATUS_SUCCESS;
1418*c2c66affSColin Finck     PVCB     Vcb = NULL;
1419*c2c66affSColin Finck     SHORT    i;
1420*c2c66affSColin Finck 
1421*c2c66affSColin Finck     BOOLEAN VCBResourceInit     = FALSE;
1422*c2c66affSColin Finck     BOOLEAN BitMapResource1Init = FALSE;
1423*c2c66affSColin Finck     BOOLEAN FcbListResourceInit = FALSE;
1424*c2c66affSColin Finck     BOOLEAN FileIdResourceInit  = FALSE;
1425*c2c66affSColin Finck     BOOLEAN DlocResourceInit    = FALSE;
1426*c2c66affSColin Finck     BOOLEAN DlocResource2Init   = FALSE;
1427*c2c66affSColin Finck     BOOLEAN FlushResourceInit   = FALSE;
1428*c2c66affSColin Finck     BOOLEAN PreallocResourceInit= FALSE;
1429*c2c66affSColin Finck     BOOLEAN IoResourceInit      = FALSE;
1430*c2c66affSColin Finck 
1431*c2c66affSColin Finck     Vcb = (PVCB)(PtrVolumeDeviceObject->DeviceExtension);
1432*c2c66affSColin Finck 
1433*c2c66affSColin Finck     _SEH2_TRY {
1434*c2c66affSColin Finck     // Zero it out (typically this has already been done by the I/O
1435*c2c66affSColin Finck     // Manager but it does not hurt to do it again)!
1436*c2c66affSColin Finck     RtlZeroMemory(Vcb, sizeof(VCB));
1437*c2c66affSColin Finck 
1438*c2c66affSColin Finck     // Initialize the signature fields
1439*c2c66affSColin Finck     Vcb->NodeIdentifier.NodeType = UDF_NODE_TYPE_VCB;
1440*c2c66affSColin Finck     Vcb->NodeIdentifier.NodeSize = sizeof(VCB);
1441*c2c66affSColin Finck 
1442*c2c66affSColin Finck     // Initialize the ERESOURCE object.
1443*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->VCBResource));
1444*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1445*c2c66affSColin Finck         try_return(RC);
1446*c2c66affSColin Finck     VCBResourceInit = TRUE;
1447*c2c66affSColin Finck 
1448*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->BitMapResource1));
1449*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1450*c2c66affSColin Finck         try_return(RC);
1451*c2c66affSColin Finck     BitMapResource1Init = TRUE;
1452*c2c66affSColin Finck 
1453*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->FcbListResource));
1454*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1455*c2c66affSColin Finck         try_return(RC);
1456*c2c66affSColin Finck     FcbListResourceInit = TRUE;
1457*c2c66affSColin Finck 
1458*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->FileIdResource));
1459*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1460*c2c66affSColin Finck         try_return(RC);
1461*c2c66affSColin Finck     FileIdResourceInit = TRUE;
1462*c2c66affSColin Finck 
1463*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->DlocResource));
1464*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1465*c2c66affSColin Finck         try_return(RC);
1466*c2c66affSColin Finck     DlocResourceInit = TRUE;
1467*c2c66affSColin Finck 
1468*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->DlocResource2));
1469*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1470*c2c66affSColin Finck         try_return(RC);
1471*c2c66affSColin Finck     DlocResource2Init = TRUE;
1472*c2c66affSColin Finck 
1473*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->FlushResource));
1474*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1475*c2c66affSColin Finck         try_return(RC);
1476*c2c66affSColin Finck     FlushResourceInit = TRUE;
1477*c2c66affSColin Finck 
1478*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->PreallocResource));
1479*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1480*c2c66affSColin Finck         try_return(RC);
1481*c2c66affSColin Finck     PreallocResourceInit = TRUE;
1482*c2c66affSColin Finck 
1483*c2c66affSColin Finck     RC = UDFInitializeResourceLite(&(Vcb->IoResource));
1484*c2c66affSColin Finck     if(!NT_SUCCESS(RC))
1485*c2c66affSColin Finck         try_return(RC);
1486*c2c66affSColin Finck     IoResourceInit = TRUE;
1487*c2c66affSColin Finck 
1488*c2c66affSColin Finck //    RC = UDFInitializeResourceLite(&(Vcb->DelayedCloseResource));
1489*c2c66affSColin Finck //    ASSERT(NT_SUCCESS(RC));
1490*c2c66affSColin Finck 
1491*c2c66affSColin Finck     // Allocate buffer for statistics
1492*c2c66affSColin Finck     Vcb->Statistics = (PFILE_SYSTEM_STATISTICS)MyAllocatePool__(NonPagedPool, sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors );
1493*c2c66affSColin Finck     if(!Vcb->Statistics)
1494*c2c66affSColin Finck         try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
1495*c2c66affSColin Finck     RtlZeroMemory( Vcb->Statistics, sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors );
1496*c2c66affSColin Finck     for (i=0; i < (KeNumberProcessors); i++) {
1497*c2c66affSColin Finck         Vcb->Statistics[i].Common.FileSystemType = FILESYSTEM_STATISTICS_TYPE_NTFS;
1498*c2c66affSColin Finck         Vcb->Statistics[i].Common.Version = 1;
1499*c2c66affSColin Finck         Vcb->Statistics[i].Common.SizeOfCompleteStructure =
1500*c2c66affSColin Finck             sizeof(FILE_SYSTEM_STATISTICS);
1501*c2c66affSColin Finck     }
1502*c2c66affSColin Finck 
1503*c2c66affSColin Finck     // We know the target device object.
1504*c2c66affSColin Finck     // Note that this is not neccessarily a pointer to the actual
1505*c2c66affSColin Finck     // physical/virtual device on which the logical volume should
1506*c2c66affSColin Finck     // be mounted. This is actually a pointer to either the actual
1507*c2c66affSColin Finck     // (real) device or to any device object that may have been
1508*c2c66affSColin Finck     // attached to it. Any IRPs that we send down should be sent to this
1509*c2c66affSColin Finck     // device object. However, the "real" physical/virtual device object
1510*c2c66affSColin Finck     // on which we perform our mount operation can be determined from the
1511*c2c66affSColin Finck     // RealDevice field in the VPB sent to us.
1512*c2c66affSColin Finck     Vcb->TargetDeviceObject = PtrTargetDeviceObject;
1513*c2c66affSColin Finck 
1514*c2c66affSColin Finck     // We also have a pointer to the newly created device object representing
1515*c2c66affSColin Finck     // this logical volume (remember that this VCB structure is simply an
1516*c2c66affSColin Finck     // extension of the created device object).
1517*c2c66affSColin Finck     Vcb->VCBDeviceObject = PtrVolumeDeviceObject;
1518*c2c66affSColin Finck 
1519*c2c66affSColin Finck     // We also have the VPB pointer. This was obtained from the
1520*c2c66affSColin Finck     // Parameters.MountVolume.Vpb field in the current I/O stack location
1521*c2c66affSColin Finck     // for the mount IRP.
1522*c2c66affSColin Finck     Vcb->Vpb = PtrVPB;
1523*c2c66affSColin Finck     // Target Vcb field in Vcb onto itself. This required for check in
1524*c2c66affSColin Finck     // open/lock/unlock volume dispatch poits
1525*c2c66affSColin Finck     Vcb->Vcb=Vcb;
1526*c2c66affSColin Finck 
1527*c2c66affSColin Finck     //  Set the removable media flag based on the real device's
1528*c2c66affSColin Finck     //  characteristics
1529*c2c66affSColin Finck     if (PtrVPB->RealDevice->Characteristics & FILE_REMOVABLE_MEDIA) {
1530*c2c66affSColin Finck         Vcb->VCBFlags |= UDF_VCB_FLAGS_REMOVABLE_MEDIA;
1531*c2c66affSColin Finck     }
1532*c2c66affSColin Finck 
1533*c2c66affSColin Finck     // Initialize the list anchor (head) for some lists in this VCB.
1534*c2c66affSColin Finck     InitializeListHead(&(Vcb->NextFCB));
1535*c2c66affSColin Finck     InitializeListHead(&(Vcb->NextNotifyIRP));
1536*c2c66affSColin Finck     InitializeListHead(&(Vcb->VolumeOpenListHead));
1537*c2c66affSColin Finck 
1538*c2c66affSColin Finck     //  Initialize the overflow queue for the volume
1539*c2c66affSColin Finck     Vcb->OverflowQueueCount = 0;
1540*c2c66affSColin Finck     InitializeListHead(&(Vcb->OverflowQueue));
1541*c2c66affSColin Finck 
1542*c2c66affSColin Finck     Vcb->PostedRequestCount = 0;
1543*c2c66affSColin Finck     KeInitializeSpinLock(&(Vcb->OverflowQueueSpinLock));
1544*c2c66affSColin Finck 
1545*c2c66affSColin Finck     // Initialize the notify IRP list mutex
1546*c2c66affSColin Finck     FsRtlNotifyInitializeSync(&(Vcb->NotifyIRPMutex));
1547*c2c66affSColin Finck 
1548*c2c66affSColin Finck     // Intilize NtRequiredFCB for this VCB
1549*c2c66affSColin Finck     Vcb->NTRequiredFCB = (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
1550*c2c66affSColin Finck     if(!Vcb->NTRequiredFCB)
1551*c2c66affSColin Finck         try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
1552*c2c66affSColin Finck     RtlZeroMemory(Vcb->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB)));
1553*c2c66affSColin Finck 
1554*c2c66affSColin Finck     // Set the initial file size values appropriately. Note that our FSD may
1555*c2c66affSColin Finck     // wish to guess at the initial amount of information we would like to
1556*c2c66affSColin Finck     // read from the disk until we have really determined that this a valid
1557*c2c66affSColin Finck     // logical volume (on disk) that we wish to mount.
1558*c2c66affSColin Finck     // Vcb->FileSize = Vcb->AllocationSize = ??
1559*c2c66affSColin Finck 
1560*c2c66affSColin Finck     // We do not want to bother with valid data length callbacks
1561*c2c66affSColin Finck     // from the Cache Manager for the file stream opened for volume metadata
1562*c2c66affSColin Finck     // information
1563*c2c66affSColin Finck     Vcb->NTRequiredFCB->CommonFCBHeader.ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFULL;
1564*c2c66affSColin Finck 
1565*c2c66affSColin Finck     Vcb->VolumeLockPID = -1;
1566*c2c66affSColin Finck 
1567*c2c66affSColin Finck     Vcb->VCBOpenCount = 1;
1568*c2c66affSColin Finck 
1569*c2c66affSColin Finck     Vcb->WCacheMaxBlocks        = UDFGlobalData.WCacheMaxBlocks;
1570*c2c66affSColin Finck     Vcb->WCacheMaxFrames        = UDFGlobalData.WCacheMaxFrames;
1571*c2c66affSColin Finck     Vcb->WCacheBlocksPerFrameSh = UDFGlobalData.WCacheBlocksPerFrameSh;
1572*c2c66affSColin Finck     Vcb->WCacheFramesToKeepFree = UDFGlobalData.WCacheFramesToKeepFree;
1573*c2c66affSColin Finck 
1574*c2c66affSColin Finck     // Create a stream file object for this volume.
1575*c2c66affSColin Finck     //Vcb->PtrStreamFileObject = IoCreateStreamFileObject(NULL,
1576*c2c66affSColin Finck     //                                            Vcb->Vpb->RealDevice);
1577*c2c66affSColin Finck     //ASSERT(Vcb->PtrStreamFileObject);
1578*c2c66affSColin Finck 
1579*c2c66affSColin Finck     // Initialize some important fields in the newly created file object.
1580*c2c66affSColin Finck     //Vcb->PtrStreamFileObject->FsContext = (PVOID)Vcb;
1581*c2c66affSColin Finck     //Vcb->PtrStreamFileObject->FsContext2 = NULL;
1582*c2c66affSColin Finck     //Vcb->PtrStreamFileObject->SectionObjectPointer = &(Vcb->SectionObject);
1583*c2c66affSColin Finck 
1584*c2c66affSColin Finck     //Vcb->PtrStreamFileObject->Vpb = PtrVPB;
1585*c2c66affSColin Finck 
1586*c2c66affSColin Finck     // Link this chap onto the global linked list of all VCB structures.
1587*c2c66affSColin Finck     // We consider that GlobalDataResource was acquired in past
1588*c2c66affSColin Finck     UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
1589*c2c66affSColin Finck     InsertTailList(&(UDFGlobalData.VCBQueue), &(Vcb->NextVCB));
1590*c2c66affSColin Finck 
1591*c2c66affSColin Finck     Vcb->TargetDevName.Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, sizeof(MOUNTDEV_NAME));
1592*c2c66affSColin Finck     if(!Vcb->TargetDevName.Buffer)
1593*c2c66affSColin Finck         try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
1594*c2c66affSColin Finck 
1595*c2c66affSColin Finck     RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_DEVICE_NAME /*IOCTL_MOUNTDEV_QUERY_DEVICE_NAME*/, Vcb->TargetDeviceObject,
1596*c2c66affSColin Finck                     NULL,0,
1597*c2c66affSColin Finck                     (PVOID)(Vcb->TargetDevName.Buffer),sizeof(MOUNTDEV_NAME),
1598*c2c66affSColin Finck                     FALSE, NULL);
1599*c2c66affSColin Finck     if(!NT_SUCCESS(RC)) {
1600*c2c66affSColin Finck 
1601*c2c66affSColin Finck         if(RC == STATUS_BUFFER_OVERFLOW) {
1602*c2c66affSColin Finck             if(!MyReallocPool__((PCHAR)(Vcb->TargetDevName.Buffer), sizeof(MOUNTDEV_NAME),
1603*c2c66affSColin Finck                              (PCHAR*)&(Vcb->TargetDevName.Buffer), Vcb->TargetDevName.Buffer[0]+sizeof(MOUNTDEV_NAME)) ) {
1604*c2c66affSColin Finck                 goto Kill_DevName_buffer;
1605*c2c66affSColin Finck             }
1606*c2c66affSColin Finck 
1607*c2c66affSColin Finck             RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_DEVICE_NAME /*IOCTL_MOUNTDEV_QUERY_DEVICE_NAME*/, Vcb->TargetDeviceObject,
1608*c2c66affSColin Finck                             NULL,0,
1609*c2c66affSColin Finck                             (PVOID)(Vcb->TargetDevName.Buffer), Vcb->TargetDevName.Buffer[0]+sizeof(MOUNTDEV_NAME),
1610*c2c66affSColin Finck                             FALSE, NULL);
1611*c2c66affSColin Finck             if(!NT_SUCCESS(RC))
1612*c2c66affSColin Finck                 goto Kill_DevName_buffer;
1613*c2c66affSColin Finck 
1614*c2c66affSColin Finck         } else {
1615*c2c66affSColin Finck Kill_DevName_buffer:
1616*c2c66affSColin Finck             if(!MyReallocPool__((PCHAR)Vcb->TargetDevName.Buffer, sizeof(MOUNTDEV_NAME),
1617*c2c66affSColin Finck                                 (PCHAR*)&(Vcb->TargetDevName.Buffer), sizeof(REG_NAMELESS_DEV)))
1618*c2c66affSColin Finck                 try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
1619*c2c66affSColin Finck             RtlCopyMemory(Vcb->TargetDevName.Buffer, REG_NAMELESS_DEV, sizeof(REG_NAMELESS_DEV));
1620*c2c66affSColin Finck             Vcb->TargetDevName.Length = sizeof(REG_NAMELESS_DEV)-sizeof(WCHAR);
1621*c2c66affSColin Finck             Vcb->TargetDevName.MaximumLength = sizeof(REG_NAMELESS_DEV);
1622*c2c66affSColin Finck             goto read_reg;
1623*c2c66affSColin Finck         }
1624*c2c66affSColin Finck     }
1625*c2c66affSColin Finck 
1626*c2c66affSColin Finck     Vcb->TargetDevName.MaximumLength =
1627*c2c66affSColin Finck     (Vcb->TargetDevName.Length = Vcb->TargetDevName.Buffer[0]) + sizeof(WCHAR);
1628*c2c66affSColin Finck     RtlMoveMemory((PVOID)(Vcb->TargetDevName.Buffer), (PVOID)(Vcb->TargetDevName.Buffer+1), Vcb->TargetDevName.Buffer[0]);
1629*c2c66affSColin Finck     Vcb->TargetDevName.Buffer[i = (SHORT)(Vcb->TargetDevName.Length/sizeof(WCHAR))] = 0;
1630*c2c66affSColin Finck 
1631*c2c66affSColin Finck     for(;i>=0;i--) {
1632*c2c66affSColin Finck         if(Vcb->TargetDevName.Buffer[i] == L'\\') {
1633*c2c66affSColin Finck 
1634*c2c66affSColin Finck             Vcb->TargetDevName.Length -= i*sizeof(WCHAR);
1635*c2c66affSColin Finck             RtlMoveMemory((PVOID)(Vcb->TargetDevName.Buffer), (PVOID)(Vcb->TargetDevName.Buffer+i), Vcb->TargetDevName.Length);
1636*c2c66affSColin Finck             Vcb->TargetDevName.Buffer[Vcb->TargetDevName.Length/sizeof(WCHAR)] = 0;
1637*c2c66affSColin Finck             break;
1638*c2c66affSColin Finck         }
1639*c2c66affSColin Finck     }
1640*c2c66affSColin Finck 
1641*c2c66affSColin Finck     UDFPrint(("  TargetDevName: %S\n", Vcb->TargetDevName.Buffer));
1642*c2c66affSColin Finck 
1643*c2c66affSColin Finck     // Initialize caching for the stream file object.
1644*c2c66affSColin Finck     //CcInitializeCacheMap(Vcb->PtrStreamFileObject, (PCC_FILE_SIZES)(&(Vcb->AllocationSize)),
1645*c2c66affSColin Finck     //                            TRUE,       // We will use pinned access.
1646*c2c66affSColin Finck     //                            &(UDFGlobalData.CacheMgrCallBacks), Vcb);
1647*c2c66affSColin Finck 
1648*c2c66affSColin Finck read_reg:
1649*c2c66affSColin Finck 
1650*c2c66affSColin Finck     UDFReleaseResource(&(UDFGlobalData.GlobalDataResource));
1651*c2c66affSColin Finck 
1652*c2c66affSColin Finck     // Mark the fact that this VCB structure is initialized.
1653*c2c66affSColin Finck     Vcb->VCBFlags |= UDF_VCB_FLAGS_VCB_INITIALIZED;
1654*c2c66affSColin Finck 
1655*c2c66affSColin Finck     RC = STATUS_SUCCESS;
1656*c2c66affSColin Finck 
1657*c2c66affSColin Finck try_exit:   NOTHING;
1658*c2c66affSColin Finck 
1659*c2c66affSColin Finck     } _SEH2_FINALLY {
1660*c2c66affSColin Finck 
1661*c2c66affSColin Finck         if(!NT_SUCCESS(RC)) {
1662*c2c66affSColin Finck             if(Vcb->TargetDevName.Buffer)
1663*c2c66affSColin Finck                 MyFreePool__(Vcb->TargetDevName.Buffer);
1664*c2c66affSColin Finck             if(Vcb->NTRequiredFCB)
1665*c2c66affSColin Finck                 MyFreePool__(Vcb->NTRequiredFCB);
1666*c2c66affSColin Finck             if(Vcb->Statistics)
1667*c2c66affSColin Finck                 MyFreePool__(Vcb->Statistics);
1668*c2c66affSColin Finck 
1669*c2c66affSColin Finck             if(VCBResourceInit)
1670*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->VCBResource));
1671*c2c66affSColin Finck             if(BitMapResource1Init)
1672*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->BitMapResource1));
1673*c2c66affSColin Finck             if(FcbListResourceInit)
1674*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->FcbListResource));
1675*c2c66affSColin Finck             if(FileIdResourceInit)
1676*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->FileIdResource));
1677*c2c66affSColin Finck             if(DlocResourceInit)
1678*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->DlocResource));
1679*c2c66affSColin Finck             if(DlocResource2Init)
1680*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->DlocResource2));
1681*c2c66affSColin Finck             if(FlushResourceInit)
1682*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->FlushResource));
1683*c2c66affSColin Finck             if(PreallocResourceInit)
1684*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->PreallocResource));
1685*c2c66affSColin Finck             if(IoResourceInit)
1686*c2c66affSColin Finck                 UDFDeleteResource(&(Vcb->IoResource));
1687*c2c66affSColin Finck         }
1688*c2c66affSColin Finck     } _SEH2_END;
1689*c2c66affSColin Finck 
1690*c2c66affSColin Finck     return RC;
1691*c2c66affSColin Finck } // end UDFInitializeVCB()
1692*c2c66affSColin Finck 
1693*c2c66affSColin Finck UDFFSD_MEDIA_TYPE
UDFGetMediaClass(PVCB Vcb)1694*c2c66affSColin Finck UDFGetMediaClass(
1695*c2c66affSColin Finck     PVCB Vcb
1696*c2c66affSColin Finck     )
1697*c2c66affSColin Finck {
1698*c2c66affSColin Finck     switch(Vcb->FsDeviceType) {
1699*c2c66affSColin Finck     case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
1700*c2c66affSColin Finck         if(Vcb->VCBFlags & (UDF_VCB_FLAGS_VOLUME_READ_ONLY |
1701*c2c66affSColin Finck                             UDF_VCB_FLAGS_MEDIA_READ_ONLY))
1702*c2c66affSColin Finck             return MediaCdrom;
1703*c2c66affSColin Finck         if(Vcb->CDR_Mode)
1704*c2c66affSColin Finck             return MediaCdr;
1705*c2c66affSColin Finck         if((Vcb->MediaType >= MediaType_UnknownSize_CDR) &&
1706*c2c66affSColin Finck            (Vcb->MediaType < MediaType_UnknownSize_CDRW)) {
1707*c2c66affSColin Finck             return MediaCdr;
1708*c2c66affSColin Finck         }
1709*c2c66affSColin Finck         if((Vcb->MediaType >= MediaType_UnknownSize_CDRW) &&
1710*c2c66affSColin Finck            (Vcb->MediaType < MediaType_UnknownSize_Unknown)) {
1711*c2c66affSColin Finck             return MediaCdrw;
1712*c2c66affSColin Finck         }
1713*c2c66affSColin Finck         if(Vcb->MediaClassEx == CdMediaClass_CDR) {
1714*c2c66affSColin Finck             return MediaCdr;
1715*c2c66affSColin Finck         }
1716*c2c66affSColin Finck         if(Vcb->MediaClassEx == CdMediaClass_DVDR ||
1717*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_DVDpR ||
1718*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_HD_DVDR ||
1719*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_BDR) {
1720*c2c66affSColin Finck             return MediaDvdr;
1721*c2c66affSColin Finck         }
1722*c2c66affSColin Finck         if(Vcb->MediaClassEx == CdMediaClass_CDRW) {
1723*c2c66affSColin Finck             return MediaCdrw;
1724*c2c66affSColin Finck         }
1725*c2c66affSColin Finck         if(Vcb->MediaClassEx == CdMediaClass_DVDRW ||
1726*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_DVDpRW ||
1727*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_DVDRAM ||
1728*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_HD_DVDRW ||
1729*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_HD_DVDRAM ||
1730*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_BDRE) {
1731*c2c66affSColin Finck             return MediaDvdrw;
1732*c2c66affSColin Finck         }
1733*c2c66affSColin Finck         //
1734*c2c66affSColin Finck         if(Vcb->MediaClassEx == CdMediaClass_CDROM ||
1735*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_DVDROM ||
1736*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_HD_DVDROM ||
1737*c2c66affSColin Finck            Vcb->MediaClassEx == CdMediaClass_BDROM) {
1738*c2c66affSColin Finck             return MediaCdrom;
1739*c2c66affSColin Finck         }
1740*c2c66affSColin Finck         return MediaCdrom;
1741*c2c66affSColin Finck #ifdef UDF_HDD_SUPPORT
1742*c2c66affSColin Finck     case FILE_DEVICE_DISK_FILE_SYSTEM:
1743*c2c66affSColin Finck         if(Vcb->TargetDeviceObject->Characteristics & FILE_FLOPPY_DISKETTE)
1744*c2c66affSColin Finck             return MediaFloppy;
1745*c2c66affSColin Finck         if(Vcb->TargetDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
1746*c2c66affSColin Finck             return MediaZip;
1747*c2c66affSColin Finck         return MediaHdd;
1748*c2c66affSColin Finck #endif //UDF_HDD_SUPPORT
1749*c2c66affSColin Finck     }
1750*c2c66affSColin Finck     return MediaUnknown;
1751*c2c66affSColin Finck } // end UDFGetMediaClass()
1752*c2c66affSColin Finck 
1753*c2c66affSColin Finck typedef ULONG
1754*c2c66affSColin Finck (*ptrUDFGetParameter)(
1755*c2c66affSColin Finck     IN PVCB Vcb,
1756*c2c66affSColin Finck     IN PCWSTR Name,
1757*c2c66affSColin Finck     IN ULONG DefValue
1758*c2c66affSColin Finck     );
1759*c2c66affSColin Finck 
1760*c2c66affSColin Finck VOID
UDFUpdateCompatOption(PVCB Vcb,BOOLEAN Update,BOOLEAN UseCfg,PCWSTR Name,ULONG Flag,BOOLEAN Default)1761*c2c66affSColin Finck UDFUpdateCompatOption(
1762*c2c66affSColin Finck     PVCB Vcb,
1763*c2c66affSColin Finck     BOOLEAN Update,
1764*c2c66affSColin Finck     BOOLEAN UseCfg,
1765*c2c66affSColin Finck     PCWSTR Name,
1766*c2c66affSColin Finck     ULONG Flag,
1767*c2c66affSColin Finck     BOOLEAN Default
1768*c2c66affSColin Finck     )
1769*c2c66affSColin Finck {
1770*c2c66affSColin Finck     ptrUDFGetParameter UDFGetParameter = UseCfg ? UDFGetCfgParameter : UDFGetRegParameter;
1771*c2c66affSColin Finck 
1772*c2c66affSColin Finck     if(UDFGetParameter(Vcb, Name, Update ? ((Vcb->CompatFlags & Flag) ? TRUE : FALSE) : Default)) {
1773*c2c66affSColin Finck         Vcb->CompatFlags |= Flag;
1774*c2c66affSColin Finck     } else {
1775*c2c66affSColin Finck         Vcb->CompatFlags &= ~Flag;
1776*c2c66affSColin Finck     }
1777*c2c66affSColin Finck } // end UDFUpdateCompatOption()
1778*c2c66affSColin Finck 
1779*c2c66affSColin Finck VOID
UDFReadRegKeys(PVCB Vcb,BOOLEAN Update,BOOLEAN UseCfg)1780*c2c66affSColin Finck UDFReadRegKeys(
1781*c2c66affSColin Finck     PVCB Vcb,
1782*c2c66affSColin Finck     BOOLEAN Update,
1783*c2c66affSColin Finck     BOOLEAN UseCfg
1784*c2c66affSColin Finck     )
1785*c2c66affSColin Finck {
1786*c2c66affSColin Finck     ULONG mult = 1;
1787*c2c66affSColin Finck     ptrUDFGetParameter UDFGetParameter = UseCfg ? UDFGetCfgParameter : UDFGetRegParameter;
1788*c2c66affSColin Finck 
1789*c2c66affSColin Finck     Vcb->DefaultRegName = UDFMediaClassName[(ULONG)UDFGetMediaClass(Vcb)].ClassName;
1790*c2c66affSColin Finck 
1791*c2c66affSColin Finck     // Should we use Extended FE by default ?
1792*c2c66affSColin Finck     Vcb->UseExtendedFE = (UCHAR)UDFGetParameter(Vcb, REG_USEEXTENDEDFE_NAME,
1793*c2c66affSColin Finck         Update ? Vcb->UseExtendedFE : FALSE);
1794*c2c66affSColin Finck     if(Vcb->UseExtendedFE != TRUE) Vcb->UseExtendedFE = FALSE;
1795*c2c66affSColin Finck     // What type of AllocDescs should we use
1796*c2c66affSColin Finck     Vcb->DefaultAllocMode = (USHORT)UDFGetParameter(Vcb, REG_DEFALLOCMODE_NAME,
1797*c2c66affSColin Finck         Update ? Vcb->DefaultAllocMode : ICB_FLAG_AD_SHORT);
1798*c2c66affSColin Finck     if(Vcb->DefaultAllocMode > ICB_FLAG_AD_LONG) Vcb->DefaultAllocMode = ICB_FLAG_AD_SHORT;
1799*c2c66affSColin Finck     // Default UID & GID to be set on newly created files
1800*c2c66affSColin Finck     Vcb->DefaultUID = UDFGetParameter(Vcb, UDF_DEFAULT_UID_NAME, Update ? Vcb->DefaultUID : -1);
1801*c2c66affSColin Finck     Vcb->DefaultGID = UDFGetParameter(Vcb, UDF_DEFAULT_GID_NAME, Update ? Vcb->DefaultGID : -1);
1802*c2c66affSColin Finck     // FE allocation charge for plain Dirs
1803*c2c66affSColin Finck     Vcb->FECharge = UDFGetParameter(Vcb, UDF_FE_CHARGE_NAME, Update ? Vcb->FECharge : 0);
1804*c2c66affSColin Finck     if(!Vcb->FECharge)
1805*c2c66affSColin Finck         Vcb->FECharge = UDF_DEFAULT_FE_CHARGE;
1806*c2c66affSColin Finck     // FE allocation charge for Stream Dirs (SDir)
1807*c2c66affSColin Finck     Vcb->FEChargeSDir = UDFGetParameter(Vcb, UDF_FE_CHARGE_SDIR_NAME,
1808*c2c66affSColin Finck         Update ? Vcb->FEChargeSDir : 0);
1809*c2c66affSColin Finck     if(!Vcb->FEChargeSDir)
1810*c2c66affSColin Finck         Vcb->FEChargeSDir = UDF_DEFAULT_FE_CHARGE_SDIR;
1811*c2c66affSColin Finck     // How many Deleted entries should contain Directory to make us
1812*c2c66affSColin Finck     // start packing it.
1813*c2c66affSColin Finck     Vcb->PackDirThreshold = UDFGetParameter(Vcb, UDF_DIR_PACK_THRESHOLD_NAME,
1814*c2c66affSColin Finck         Update ? Vcb->PackDirThreshold : 0);
1815*c2c66affSColin Finck     if(Vcb->PackDirThreshold == 0xffffffff)
1816*c2c66affSColin Finck         Vcb->PackDirThreshold = UDF_DEFAULT_DIR_PACK_THRESHOLD;
1817*c2c66affSColin Finck     // The binary exponent for the number of Pages to be read-ahead'ed
1818*c2c66affSColin Finck     // This information would be sent to System Cache Manager
1819*c2c66affSColin Finck     if(!Update) {
1820*c2c66affSColin Finck         Vcb->SystemCacheGran = (1 << UDFGetParameter(Vcb, UDF_READAHEAD_GRAN_NAME, 0)) * PAGE_SIZE;
1821*c2c66affSColin Finck         if(!Vcb->SystemCacheGran)
1822*c2c66affSColin Finck             Vcb->SystemCacheGran = UDF_DEFAULT_READAHEAD_GRAN;
1823*c2c66affSColin Finck     }
1824*c2c66affSColin Finck     // Timeouts for FreeSpaceBitMap & TheWholeDirTree flushes
1825*c2c66affSColin Finck     Vcb->BM_FlushPriod = UDFGetParameter(Vcb, UDF_BM_FLUSH_PERIOD_NAME,
1826*c2c66affSColin Finck         Update ? Vcb->BM_FlushPriod : 0);
1827*c2c66affSColin Finck     if(!Vcb->BM_FlushPriod) {
1828*c2c66affSColin Finck         Vcb->BM_FlushPriod = UDF_DEFAULT_BM_FLUSH_TIMEOUT;
1829*c2c66affSColin Finck     } else
1830*c2c66affSColin Finck     if(Vcb->BM_FlushPriod == (ULONG)-1) {
1831*c2c66affSColin Finck         Vcb->BM_FlushPriod = 0;
1832*c2c66affSColin Finck     }
1833*c2c66affSColin Finck     Vcb->Tree_FlushPriod = UDFGetParameter(Vcb, UDF_TREE_FLUSH_PERIOD_NAME,
1834*c2c66affSColin Finck         Update ? Vcb->Tree_FlushPriod : 0);
1835*c2c66affSColin Finck     if(!Vcb->Tree_FlushPriod) {
1836*c2c66affSColin Finck         Vcb->Tree_FlushPriod = UDF_DEFAULT_TREE_FLUSH_TIMEOUT;
1837*c2c66affSColin Finck     } else
1838*c2c66affSColin Finck     if(Vcb->Tree_FlushPriod == (ULONG)-1) {
1839*c2c66affSColin Finck         Vcb->Tree_FlushPriod = 0;
1840*c2c66affSColin Finck     }
1841*c2c66affSColin Finck     Vcb->SkipCountLimit = UDFGetParameter(Vcb, UDF_NO_UPDATE_PERIOD_NAME,
1842*c2c66affSColin Finck         Update ? Vcb->SkipCountLimit : 0);
1843*c2c66affSColin Finck     if(!Vcb->SkipCountLimit)
1844*c2c66affSColin Finck         Vcb->SkipCountLimit = -1;
1845*c2c66affSColin Finck 
1846*c2c66affSColin Finck     Vcb->SkipEjectCountLimit = UDFGetParameter(Vcb, UDF_NO_EJECT_PERIOD_NAME,
1847*c2c66affSColin Finck         Update ? Vcb->SkipEjectCountLimit : 3);
1848*c2c66affSColin Finck 
1849*c2c66affSColin Finck     if(!Update) {
1850*c2c66affSColin Finck         // How many threads are allowed to sodomize Disc simultaneously on each CPU
1851*c2c66affSColin Finck         Vcb->ThreadsPerCpu = UDFGetParameter(Vcb, UDF_FSP_THREAD_PER_CPU_NAME,
1852*c2c66affSColin Finck             Update ? Vcb->ThreadsPerCpu : 2);
1853*c2c66affSColin Finck         if(Vcb->ThreadsPerCpu < 2)
1854*c2c66affSColin Finck             Vcb->ThreadsPerCpu = UDF_DEFAULT_FSP_THREAD_PER_CPU;
1855*c2c66affSColin Finck     }
1856*c2c66affSColin Finck     // The mimimum FileSize increment when we'll decide not to allocate
1857*c2c66affSColin Finck     // on-disk space.
1858*c2c66affSColin Finck     Vcb->SparseThreshold = UDFGetParameter(Vcb, UDF_SPARSE_THRESHOLD_NAME,
1859*c2c66affSColin Finck         Update ? Vcb->SparseThreshold : 0);
1860*c2c66affSColin Finck     if(!Vcb->SparseThreshold)
1861*c2c66affSColin Finck         Vcb->SparseThreshold = UDF_DEFAULT_SPARSE_THRESHOLD;
1862*c2c66affSColin Finck     // This option is used to VERIFY all the data written. It decreases performance
1863*c2c66affSColin Finck     Vcb->VerifyOnWrite = UDFGetParameter(Vcb, UDF_VERIFY_ON_WRITE_NAME,
1864*c2c66affSColin Finck         Update ? Vcb->VerifyOnWrite : FALSE) ? TRUE : FALSE;
1865*c2c66affSColin Finck 
1866*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1867*c2c66affSColin Finck     // Should we update AttrFileTime on Attr changes
1868*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_TIMES_ATTR, UDF_VCB_IC_UPDATE_ATTR_TIME, FALSE);
1869*c2c66affSColin Finck     // Should we update ModifyFileTime on Writes changes
1870*c2c66affSColin Finck     // It also affects ARCHIVE bit setting on write operations
1871*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_TIMES_MOD, UDF_VCB_IC_UPDATE_MODIFY_TIME, FALSE);
1872*c2c66affSColin Finck     // Should we update AccessFileTime on Exec & so on.
1873*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_TIMES_ACCS, UDF_VCB_IC_UPDATE_ACCESS_TIME, FALSE);
1874*c2c66affSColin Finck     // Should we update Archive bit
1875*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_ATTR_ARCH, UDF_VCB_IC_UPDATE_ARCH_BIT, FALSE);
1876*c2c66affSColin Finck     // Should we update Dir's Times & Attrs on Modify
1877*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_DIR_TIMES_ATTR_W, UDF_VCB_IC_UPDATE_DIR_WRITE, FALSE);
1878*c2c66affSColin Finck     // Should we update Dir's Times & Attrs on Access
1879*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_UPDATE_DIR_TIMES_ATTR_R, UDF_VCB_IC_UPDATE_DIR_READ, FALSE);
1880*c2c66affSColin Finck     // Should we allow user to write into Read-Only Directory
1881*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_ALLOW_WRITE_IN_RO_DIR, UDF_VCB_IC_WRITE_IN_RO_DIR, TRUE);
1882*c2c66affSColin Finck     // Should we allow user to change Access Time for unchanged Directory
1883*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_ALLOW_UPDATE_TIMES_ACCS_UCHG_DIR, UDF_VCB_IC_UPDATE_UCHG_DIR_ACCESS_TIME, FALSE);
1884*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1885*c2c66affSColin Finck     // Should we record Allocation Descriptors in W2k-compatible form
1886*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_W2K_COMPAT_ALLOC_DESCS, UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS, TRUE);
1887*c2c66affSColin Finck     // Should we read LONG_ADs with invalid PartitionReferenceNumber (generated by Nero Instant Burner)
1888*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_INSTANT_COMPAT_ALLOC_DESCS, UDF_VCB_IC_INSTANT_COMPAT_ALLOC_DESCS, TRUE);
1889*c2c66affSColin Finck     // Should we make a copy of VolumeLabel in LVD
1890*c2c66affSColin Finck     // usually only PVD is updated
1891*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_W2K_COMPAT_VLABEL, UDF_VCB_IC_W2K_COMPAT_VLABEL, TRUE);
1892*c2c66affSColin Finck     // Should we handle or ignore HW_RO flag
1893*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_HANDLE_HW_RO, UDF_VCB_IC_HW_RO, FALSE);
1894*c2c66affSColin Finck     // Should we handle or ignore SOFT_RO flag
1895*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_HANDLE_SOFT_RO, UDF_VCB_IC_SOFT_RO, TRUE);
1896*c2c66affSColin Finck 
1897*c2c66affSColin Finck     // Check if we should generate UDF-style or OS-style DOS-names
1898*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_OS_NATIVE_DOS_NAME, UDF_VCB_IC_OS_NATIVE_DOS_NAME, FALSE);
1899*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1900*c2c66affSColin Finck     // should we force FO_WRITE_THROUGH on removable media
1901*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_FORCE_WRITE_THROUGH_NAME, UDF_VCB_IC_FORCE_WRITE_THROUGH,
1902*c2c66affSColin Finck                           (Vcb->TargetDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) ? TRUE : FALSE
1903*c2c66affSColin Finck                          );
1904*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1905*c2c66affSColin Finck     // Should we ignore FO_SEQUENTIAL_ONLY
1906*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_IGNORE_SEQUENTIAL_IO, UDF_VCB_IC_IGNORE_SEQUENTIAL_IO, FALSE);
1907*c2c66affSColin Finck // Force Read-only mounts
1908*c2c66affSColin Finck #ifndef UDF_READ_ONLY_BUILD
1909*c2c66affSColin Finck     UDFUpdateCompatOption(Vcb, Update, UseCfg, UDF_FORCE_HW_RO, UDF_VCB_IC_FORCE_HW_RO, FALSE);
1910*c2c66affSColin Finck #else //UDF_READ_ONLY_BUILD
1911*c2c66affSColin Finck     Vcb->CompatFlags |= UDF_VCB_IC_FORCE_HW_RO;
1912*c2c66affSColin Finck #endif //UDF_READ_ONLY_BUILD
1913*c2c66affSColin Finck     // Check if we should send FLUSH request for File/Dir down to
1914*c2c66affSColin Finck     // underlaying driver
1915*c2c66affSColin Finck     if(UDFGetParameter(Vcb, UDF_FLUSH_MEDIA,Update ? Vcb->FlushMedia : FALSE)) {
1916*c2c66affSColin Finck         Vcb->FlushMedia = TRUE;
1917*c2c66affSColin Finck     } else {
1918*c2c66affSColin Finck         Vcb->FlushMedia = FALSE;
1919*c2c66affSColin Finck     }
1920*c2c66affSColin Finck     // compare data from packet with data to be writen there
1921*c2c66affSColin Finck     // before physical writing
1922*c2c66affSColin Finck     if(!UDFGetParameter(Vcb, UDF_COMPARE_BEFORE_WRITE, Update ? Vcb->DoNotCompareBeforeWrite : FALSE)) {
1923*c2c66affSColin Finck         Vcb->DoNotCompareBeforeWrite = TRUE;
1924*c2c66affSColin Finck     } else {
1925*c2c66affSColin Finck         Vcb->DoNotCompareBeforeWrite = FALSE;
1926*c2c66affSColin Finck     }
1927*c2c66affSColin Finck     if(!Update)  {
1928*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_CHAINED_IO, TRUE)) {
1929*c2c66affSColin Finck             Vcb->CacheChainedIo = TRUE;
1930*c2c66affSColin Finck         }
1931*c2c66affSColin Finck 
1932*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_FORCE_MOUNT_ALL, FALSE)) {
1933*c2c66affSColin Finck             Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
1934*c2c66affSColin Finck         }
1935*c2c66affSColin Finck         // Should we show Blank.Cd file on damaged/unformatted,
1936*c2c66affSColin Finck         // but UDF-compatible disks
1937*c2c66affSColin Finck         Vcb->ShowBlankCd = (UCHAR)UDFGetParameter(Vcb, UDF_SHOW_BLANK_CD, FALSE);
1938*c2c66affSColin Finck         if(Vcb->ShowBlankCd) {
1939*c2c66affSColin Finck             Vcb->CompatFlags |= UDF_VCB_IC_SHOW_BLANK_CD;
1940*c2c66affSColin Finck             if(Vcb->ShowBlankCd > 2) {
1941*c2c66affSColin Finck                 Vcb->ShowBlankCd = 2;
1942*c2c66affSColin Finck             }
1943*c2c66affSColin Finck         }
1944*c2c66affSColin Finck         // Should we wait util CD device return from
1945*c2c66affSColin Finck         // Becoming Ready state
1946*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_WAIT_CD_SPINUP, TRUE)) {
1947*c2c66affSColin Finck             Vcb->CompatFlags |= UDF_VCB_IC_WAIT_CD_SPINUP;
1948*c2c66affSColin Finck         }
1949*c2c66affSColin Finck         // Should we remenber bad VDS locations during mount
1950*c2c66affSColin Finck         // Caching will improve mount performance on bad disks, but
1951*c2c66affSColin Finck         // will degrade mauntability of unreliable discs
1952*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_CACHE_BAD_VDS, TRUE)) {
1953*c2c66affSColin Finck             Vcb->CompatFlags |= UDF_VCB_IC_CACHE_BAD_VDS;
1954*c2c66affSColin Finck         }
1955*c2c66affSColin Finck 
1956*c2c66affSColin Finck         // Set partitially damaged volume mount mode
1957*c2c66affSColin Finck         Vcb->PartitialDamagedVolumeAction = (UCHAR)UDFGetParameter(Vcb, UDF_PART_DAMAGED_BEHAVIOR, UDF_PART_DAMAGED_RW);
1958*c2c66affSColin Finck         if(Vcb->PartitialDamagedVolumeAction > 2) {
1959*c2c66affSColin Finck             Vcb->PartitialDamagedVolumeAction = UDF_PART_DAMAGED_RW;
1960*c2c66affSColin Finck         }
1961*c2c66affSColin Finck 
1962*c2c66affSColin Finck         // Set partitially damaged volume mount mode
1963*c2c66affSColin Finck         Vcb->NoFreeRelocationSpaceVolumeAction = (UCHAR)UDFGetParameter(Vcb, UDF_NO_SPARE_BEHAVIOR, UDF_PART_DAMAGED_RW);
1964*c2c66affSColin Finck         if(Vcb->NoFreeRelocationSpaceVolumeAction > 1) {
1965*c2c66affSColin Finck             Vcb->NoFreeRelocationSpaceVolumeAction = UDF_PART_DAMAGED_RW;
1966*c2c66affSColin Finck         }
1967*c2c66affSColin Finck 
1968*c2c66affSColin Finck         // Set dirty volume mount mode
1969*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_DIRTY_VOLUME_BEHAVIOR, UDF_PART_DAMAGED_RO)) {
1970*c2c66affSColin Finck             Vcb->CompatFlags |= UDF_VCB_IC_DIRTY_RO;
1971*c2c66affSColin Finck         }
1972*c2c66affSColin Finck 
1973*c2c66affSColin Finck         mult = UDFGetParameter(Vcb, UDF_CACHE_SIZE_MULTIPLIER, 1);
1974*c2c66affSColin Finck         if(!mult) mult = 1;
1975*c2c66affSColin Finck         Vcb->WCacheMaxBlocks *= mult;
1976*c2c66affSColin Finck         Vcb->WCacheMaxFrames *= mult;
1977*c2c66affSColin Finck 
1978*c2c66affSColin Finck         if(UDFGetParameter(Vcb, UDF_USE_EJECT_BUTTON, TRUE)) {
1979*c2c66affSColin Finck             Vcb->UseEvent = TRUE;
1980*c2c66affSColin Finck         }
1981*c2c66affSColin Finck     }
1982*c2c66affSColin Finck     return;
1983*c2c66affSColin Finck } // end UDFReadRegKeys()
1984*c2c66affSColin Finck 
1985*c2c66affSColin Finck ULONG
UDFGetRegParameter(IN PVCB Vcb,IN PCWSTR Name,IN ULONG DefValue)1986*c2c66affSColin Finck UDFGetRegParameter(
1987*c2c66affSColin Finck     IN PVCB Vcb,
1988*c2c66affSColin Finck     IN PCWSTR Name,
1989*c2c66affSColin Finck     IN ULONG DefValue
1990*c2c66affSColin Finck     )
1991*c2c66affSColin Finck {
1992*c2c66affSColin Finck     return UDFRegCheckParameterValue(&(UDFGlobalData.SavedRegPath),
1993*c2c66affSColin Finck                                      Name,
1994*c2c66affSColin Finck                                      Vcb ? &(Vcb->TargetDevName) : NULL,
1995*c2c66affSColin Finck                                      Vcb ? Vcb->DefaultRegName : NULL,
1996*c2c66affSColin Finck                                      DefValue);
1997*c2c66affSColin Finck } // end UDFGetRegParameter()
1998*c2c66affSColin Finck 
1999*c2c66affSColin Finck ULONG
UDFGetCfgParameter(IN PVCB Vcb,IN PCWSTR Name,IN ULONG DefValue)2000*c2c66affSColin Finck UDFGetCfgParameter(
2001*c2c66affSColin Finck     IN PVCB Vcb,
2002*c2c66affSColin Finck     IN PCWSTR Name,
2003*c2c66affSColin Finck     IN ULONG DefValue
2004*c2c66affSColin Finck     )
2005*c2c66affSColin Finck {
2006*c2c66affSColin Finck     ULONG len;
2007*c2c66affSColin Finck     CHAR NameA[128];
2008*c2c66affSColin Finck     ULONG ret_val=0;
2009*c2c66affSColin Finck     CHAR a;
2010*c2c66affSColin Finck     BOOLEAN wait_name=TRUE;
2011*c2c66affSColin Finck     BOOLEAN wait_val=FALSE;
2012*c2c66affSColin Finck     BOOLEAN wait_nl=FALSE;
2013*c2c66affSColin Finck     ULONG radix=10;
2014*c2c66affSColin Finck     ULONG i;
2015*c2c66affSColin Finck 
2016*c2c66affSColin Finck     PUCHAR Cfg    = Vcb->Cfg;
2017*c2c66affSColin Finck     ULONG  Length = Vcb->CfgLength;
2018*c2c66affSColin Finck 
2019*c2c66affSColin Finck     if(!Cfg || !Length)
2020*c2c66affSColin Finck         return DefValue;
2021*c2c66affSColin Finck 
2022*c2c66affSColin Finck     len = wcslen(Name);
2023*c2c66affSColin Finck     if(len >= sizeof(NameA))
2024*c2c66affSColin Finck         return DefValue;
2025*c2c66affSColin Finck     sprintf(NameA, "%S", Name);
2026*c2c66affSColin Finck 
2027*c2c66affSColin Finck     for(i=0; i<Length; i++) {
2028*c2c66affSColin Finck         a=Cfg[i];
2029*c2c66affSColin Finck         switch(a) {
2030*c2c66affSColin Finck         case '\n':
2031*c2c66affSColin Finck         case '\r':
2032*c2c66affSColin Finck         case ',':
2033*c2c66affSColin Finck             if(wait_val)
2034*c2c66affSColin Finck                 return DefValue;
2035*c2c66affSColin Finck             continue;
2036*c2c66affSColin Finck         case ';':
2037*c2c66affSColin Finck         case '#':
2038*c2c66affSColin Finck         case '[': // ignore sections for now, treat as comment
2039*c2c66affSColin Finck             if(!wait_name)
2040*c2c66affSColin Finck                 return DefValue;
2041*c2c66affSColin Finck             wait_nl = TRUE;
2042*c2c66affSColin Finck             continue;
2043*c2c66affSColin Finck         case '=':
2044*c2c66affSColin Finck             if(!wait_val)
2045*c2c66affSColin Finck                 return DefValue;
2046*c2c66affSColin Finck             continue;
2047*c2c66affSColin Finck         case ' ':
2048*c2c66affSColin Finck         case '\t':
2049*c2c66affSColin Finck             continue;
2050*c2c66affSColin Finck         default:
2051*c2c66affSColin Finck             if(wait_nl)
2052*c2c66affSColin Finck                 continue;
2053*c2c66affSColin Finck         }
2054*c2c66affSColin Finck         if(wait_name) {
2055*c2c66affSColin Finck             if(i+len+2 > Length)
2056*c2c66affSColin Finck                 return DefValue;
2057*c2c66affSColin Finck             if(RtlCompareMemory(Cfg+i, NameA, len) == len) {
2058*c2c66affSColin Finck                 a=Cfg[i+len];
2059*c2c66affSColin Finck                 switch(a) {
2060*c2c66affSColin Finck                 case '\n':
2061*c2c66affSColin Finck                 case '\r':
2062*c2c66affSColin Finck                 case ',':
2063*c2c66affSColin Finck                 case ';':
2064*c2c66affSColin Finck                 case '#':
2065*c2c66affSColin Finck                     return DefValue;
2066*c2c66affSColin Finck                 case '=':
2067*c2c66affSColin Finck                 case ' ':
2068*c2c66affSColin Finck                 case '\t':
2069*c2c66affSColin Finck                     break;
2070*c2c66affSColin Finck                 default:
2071*c2c66affSColin Finck                     wait_nl = TRUE;
2072*c2c66affSColin Finck                     wait_val = FALSE;
2073*c2c66affSColin Finck                     i+=len;
2074*c2c66affSColin Finck                     continue;
2075*c2c66affSColin Finck                 }
2076*c2c66affSColin Finck                 wait_name = FALSE;
2077*c2c66affSColin Finck                 wait_nl = FALSE;
2078*c2c66affSColin Finck                 wait_val = TRUE;
2079*c2c66affSColin Finck                 i+=len;
2080*c2c66affSColin Finck 
2081*c2c66affSColin Finck             } else {
2082*c2c66affSColin Finck                 wait_nl = TRUE;
2083*c2c66affSColin Finck             }
2084*c2c66affSColin Finck             continue;
2085*c2c66affSColin Finck         }
2086*c2c66affSColin Finck         if(wait_val) {
2087*c2c66affSColin Finck             if(i+3 > Length) {
2088*c2c66affSColin Finck                 if(a=='0' && Cfg[i+1]=='x') {
2089*c2c66affSColin Finck                     i+=2;
2090*c2c66affSColin Finck                     radix=16;
2091*c2c66affSColin Finck                 }
2092*c2c66affSColin Finck             }
2093*c2c66affSColin Finck             if(i >= Length) {
2094*c2c66affSColin Finck                 return DefValue;
2095*c2c66affSColin Finck             }
2096*c2c66affSColin Finck             while(i<Length) {
2097*c2c66affSColin Finck                 a=Cfg[i];
2098*c2c66affSColin Finck                 switch(a) {
2099*c2c66affSColin Finck                 case '\n':
2100*c2c66affSColin Finck                 case '\r':
2101*c2c66affSColin Finck                 case ' ':
2102*c2c66affSColin Finck                 case '\t':
2103*c2c66affSColin Finck                 case ',':
2104*c2c66affSColin Finck                 case ';':
2105*c2c66affSColin Finck                 case '#':
2106*c2c66affSColin Finck                     if(wait_val)
2107*c2c66affSColin Finck                         return DefValue;
2108*c2c66affSColin Finck                     return ret_val;
2109*c2c66affSColin Finck                 }
2110*c2c66affSColin Finck                 if(a >= '0' && a <= '9') {
2111*c2c66affSColin Finck                     a -= '0';
2112*c2c66affSColin Finck                 } else {
2113*c2c66affSColin Finck                     if(radix != 16)
2114*c2c66affSColin Finck                         return DefValue;
2115*c2c66affSColin Finck                     if(a >= 'a' && a <= 'f') {
2116*c2c66affSColin Finck                         a -= 'a';
2117*c2c66affSColin Finck                     } else
2118*c2c66affSColin Finck                     if(a >= 'A' && a <= 'F') {
2119*c2c66affSColin Finck                         a -= 'A';
2120*c2c66affSColin Finck                     } else {
2121*c2c66affSColin Finck                         return DefValue;
2122*c2c66affSColin Finck                     }
2123*c2c66affSColin Finck                     a += 0x0a;
2124*c2c66affSColin Finck                 }
2125*c2c66affSColin Finck                 ret_val = ret_val*radix + a;
2126*c2c66affSColin Finck                 wait_val = FALSE;
2127*c2c66affSColin Finck                 i++;
2128*c2c66affSColin Finck             }
2129*c2c66affSColin Finck             return ret_val;
2130*c2c66affSColin Finck         }
2131*c2c66affSColin Finck     }
2132*c2c66affSColin Finck     return DefValue;
2133*c2c66affSColin Finck 
2134*c2c66affSColin Finck } // end UDFGetCfgParameter()
2135*c2c66affSColin Finck 
2136*c2c66affSColin Finck VOID
UDFReleaseVCB(PVCB Vcb)2137*c2c66affSColin Finck UDFReleaseVCB(
2138*c2c66affSColin Finck     PVCB  Vcb
2139*c2c66affSColin Finck     )
2140*c2c66affSColin Finck {
2141*c2c66affSColin Finck     LARGE_INTEGER delay;
2142*c2c66affSColin Finck     UDFPrint(("UDFReleaseVCB\n"));
2143*c2c66affSColin Finck 
2144*c2c66affSColin Finck     delay.QuadPart = -500000; // 0.05 sec
2145*c2c66affSColin Finck     while(Vcb->PostedRequestCount) {
2146*c2c66affSColin Finck         UDFPrint(("UDFReleaseVCB: PostedRequestCount = %d\n", Vcb->PostedRequestCount));
2147*c2c66affSColin Finck         // spin until all queues IRPs are processed
2148*c2c66affSColin Finck         KeDelayExecutionThread(KernelMode, FALSE, &delay);
2149*c2c66affSColin Finck         delay.QuadPart -= 500000; // grow delay 0.05 sec
2150*c2c66affSColin Finck     }
2151*c2c66affSColin Finck 
2152*c2c66affSColin Finck     _SEH2_TRY {
2153*c2c66affSColin Finck         UDFPrint(("UDF: Flushing buffers\n"));
2154*c2c66affSColin Finck         UDFVRelease(Vcb);
2155*c2c66affSColin Finck         WCacheFlushAll__(&(Vcb->FastCache),Vcb);
2156*c2c66affSColin Finck         WCacheRelease__(&(Vcb->FastCache));
2157*c2c66affSColin Finck 
2158*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2159*c2c66affSColin Finck         BrutePoint();
2160*c2c66affSColin Finck     } _SEH2_END;
2161*c2c66affSColin Finck 
2162*c2c66affSColin Finck #ifdef UDF_DBG
2163*c2c66affSColin Finck     _SEH2_TRY {
2164*c2c66affSColin Finck         if (!ExIsResourceAcquiredShared(&UDFGlobalData.GlobalDataResource)) {
2165*c2c66affSColin Finck             UDFPrint(("UDF: attempt to access to not protected data\n"));
2166*c2c66affSColin Finck             UDFPrint(("UDF: UDFGlobalData\n"));
2167*c2c66affSColin Finck             BrutePoint();
2168*c2c66affSColin Finck         }
2169*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2170*c2c66affSColin Finck         BrutePoint();
2171*c2c66affSColin Finck     } _SEH2_END;
2172*c2c66affSColin Finck #endif
2173*c2c66affSColin Finck 
2174*c2c66affSColin Finck     _SEH2_TRY {
2175*c2c66affSColin Finck         RemoveEntryList(&(Vcb->NextVCB));
2176*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2177*c2c66affSColin Finck         BrutePoint();
2178*c2c66affSColin Finck     } _SEH2_END;
2179*c2c66affSColin Finck 
2180*c2c66affSColin Finck /*    _SEH2_TRY {
2181*c2c66affSColin Finck         if(Vcb->VCBFlags & UDF_VCB_FLAGS_STOP_WAITER_EVENT)
2182*c2c66affSColin Finck             KeWaitForSingleObject(&(Vcb->WaiterStopped), Executive, KernelMode, FALSE, NULL);
2183*c2c66affSColin Finck             Vcb->VCBFlags &= ~UDF_VCB_FLAGS_STOP_WAITER_EVENT;
2184*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2185*c2c66affSColin Finck         BrutePoint();
2186*c2c66affSColin Finck     }*/
2187*c2c66affSColin Finck 
2188*c2c66affSColin Finck     _SEH2_TRY {
2189*c2c66affSColin Finck         UDFPrint(("UDF: Delete resources\n"));
2190*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->VCBResource));
2191*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->BitMapResource1));
2192*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->FcbListResource));
2193*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->FileIdResource));
2194*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->DlocResource));
2195*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->DlocResource2));
2196*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->FlushResource));
2197*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->PreallocResource));
2198*c2c66affSColin Finck         UDFDeleteResource(&(Vcb->IoResource));
2199*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2200*c2c66affSColin Finck         BrutePoint();
2201*c2c66affSColin Finck     } _SEH2_END;
2202*c2c66affSColin Finck 
2203*c2c66affSColin Finck     _SEH2_TRY {
2204*c2c66affSColin Finck         UDFPrint(("UDF: Cleanup VCB\n"));
2205*c2c66affSColin Finck         ASSERT(IsListEmpty(&(Vcb->NextNotifyIRP)));
2206*c2c66affSColin Finck         FsRtlNotifyUninitializeSync(&(Vcb->NotifyIRPMutex));
2207*c2c66affSColin Finck         UDFCleanupVCB(Vcb);
2208*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2209*c2c66affSColin Finck         BrutePoint();
2210*c2c66affSColin Finck     } _SEH2_END;
2211*c2c66affSColin Finck 
2212*c2c66affSColin Finck     _SEH2_TRY {
2213*c2c66affSColin Finck         UDFPrint(("UDF: Delete DO\n"));
2214*c2c66affSColin Finck         IoDeleteDevice(Vcb->VCBDeviceObject);
2215*c2c66affSColin Finck     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
2216*c2c66affSColin Finck         BrutePoint();
2217*c2c66affSColin Finck     } _SEH2_END;
2218*c2c66affSColin Finck 
2219*c2c66affSColin Finck } // end UDFReleaseVCB()
2220*c2c66affSColin Finck 
2221*c2c66affSColin Finck /*
2222*c2c66affSColin Finck     Read DWORD from Registry
2223*c2c66affSColin Finck */
2224*c2c66affSColin Finck ULONG
UDFRegCheckParameterValue(IN PUNICODE_STRING RegistryPath,IN PCWSTR Name,IN PUNICODE_STRING PtrVolumePath,IN PCWSTR DefaultPath,IN ULONG DefValue)2225*c2c66affSColin Finck UDFRegCheckParameterValue(
2226*c2c66affSColin Finck     IN PUNICODE_STRING RegistryPath,
2227*c2c66affSColin Finck     IN PCWSTR Name,
2228*c2c66affSColin Finck     IN PUNICODE_STRING PtrVolumePath,
2229*c2c66affSColin Finck     IN PCWSTR DefaultPath,
2230*c2c66affSColin Finck     IN ULONG DefValue
2231*c2c66affSColin Finck     )
2232*c2c66affSColin Finck {
2233*c2c66affSColin Finck     NTSTATUS          status;
2234*c2c66affSColin Finck 
2235*c2c66affSColin Finck     ULONG             val = DefValue;
2236*c2c66affSColin Finck 
2237*c2c66affSColin Finck     UNICODE_STRING    paramStr;
2238*c2c66affSColin Finck     UNICODE_STRING    defaultParamStr;
2239*c2c66affSColin Finck     UNICODE_STRING    paramPathUnknownStr;
2240*c2c66affSColin Finck 
2241*c2c66affSColin Finck     UNICODE_STRING    paramSuffix;
2242*c2c66affSColin Finck     UNICODE_STRING    paramPath;
2243*c2c66affSColin Finck     UNICODE_STRING    paramPathUnknown;
2244*c2c66affSColin Finck     UNICODE_STRING    paramDevPath;
2245*c2c66affSColin Finck     UNICODE_STRING    defaultParamPath;
2246*c2c66affSColin Finck 
2247*c2c66affSColin Finck     _SEH2_TRY {
2248*c2c66affSColin Finck 
2249*c2c66affSColin Finck         paramPath.Buffer = NULL;
2250*c2c66affSColin Finck         paramDevPath.Buffer = NULL;
2251*c2c66affSColin Finck         paramPathUnknown.Buffer = NULL;
2252*c2c66affSColin Finck         defaultParamPath.Buffer = NULL;
2253*c2c66affSColin Finck 
2254*c2c66affSColin Finck         // First append \Parameters to the passed in registry path
2255*c2c66affSColin Finck         // Note, RtlInitUnicodeString doesn't allocate memory
2256*c2c66affSColin Finck         RtlInitUnicodeString(&paramStr, L"\\Parameters");
2257*c2c66affSColin Finck         RtlInitUnicodeString(&paramPath, NULL);
2258*c2c66affSColin Finck 
2259*c2c66affSColin Finck         RtlInitUnicodeString(&paramPathUnknownStr, REG_DEFAULT_UNKNOWN);
2260*c2c66affSColin Finck         RtlInitUnicodeString(&paramPathUnknown, NULL);
2261*c2c66affSColin Finck 
2262*c2c66affSColin Finck         paramPathUnknown.MaximumLength = RegistryPath->Length + paramPathUnknownStr.Length + paramStr.Length + sizeof(WCHAR);
2263*c2c66affSColin Finck         paramPath.MaximumLength = RegistryPath->Length + paramStr.Length + sizeof(WCHAR);
2264*c2c66affSColin Finck 
2265*c2c66affSColin Finck         paramPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramPath.MaximumLength);
2266*c2c66affSColin Finck         if(!paramPath.Buffer) {
2267*c2c66affSColin Finck             UDFPrint(("UDFCheckRegValue: couldn't allocate paramPath\n"));
2268*c2c66affSColin Finck             try_return(val = DefValue);
2269*c2c66affSColin Finck         }
2270*c2c66affSColin Finck         paramPathUnknown.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramPathUnknown.MaximumLength);
2271*c2c66affSColin Finck         if(!paramPathUnknown.Buffer) {
2272*c2c66affSColin Finck             UDFPrint(("UDFCheckRegValue: couldn't allocate paramPathUnknown\n"));
2273*c2c66affSColin Finck             try_return(val = DefValue);
2274*c2c66affSColin Finck         }
2275*c2c66affSColin Finck 
2276*c2c66affSColin Finck         RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
2277*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
2278*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2279*c2c66affSColin Finck             try_return(val = DefValue);
2280*c2c66affSColin Finck         }
2281*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramPath, paramStr.Buffer);
2282*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2283*c2c66affSColin Finck             try_return(val = DefValue);
2284*c2c66affSColin Finck         }
2285*c2c66affSColin Finck         UDFPrint(("UDFCheckRegValue: (1) |%S|\n", paramPath.Buffer));
2286*c2c66affSColin Finck 
2287*c2c66affSColin Finck         RtlZeroMemory(paramPathUnknown.Buffer, paramPathUnknown.MaximumLength);
2288*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramPathUnknown, RegistryPath->Buffer);
2289*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2290*c2c66affSColin Finck             try_return(val = DefValue);
2291*c2c66affSColin Finck         }
2292*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramPathUnknown, paramStr.Buffer);
2293*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2294*c2c66affSColin Finck             try_return(val = DefValue);
2295*c2c66affSColin Finck         }
2296*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramPathUnknown, paramPathUnknownStr.Buffer);
2297*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2298*c2c66affSColin Finck             try_return(val = DefValue);
2299*c2c66affSColin Finck         }
2300*c2c66affSColin Finck         UDFPrint(("UDFCheckRegValue: (2) |%S|\n", paramPathUnknown.Buffer));
2301*c2c66affSColin Finck 
2302*c2c66affSColin Finck         // First append \Parameters\Default_XXX to the passed in registry path
2303*c2c66affSColin Finck         if(DefaultPath) {
2304*c2c66affSColin Finck             RtlInitUnicodeString(&defaultParamStr, DefaultPath);
2305*c2c66affSColin Finck             RtlInitUnicodeString(&defaultParamPath, NULL);
2306*c2c66affSColin Finck             defaultParamPath.MaximumLength = paramPath.Length + defaultParamStr.Length + sizeof(WCHAR);
2307*c2c66affSColin Finck             defaultParamPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, defaultParamPath.MaximumLength);
2308*c2c66affSColin Finck             if(!defaultParamPath.Buffer) {
2309*c2c66affSColin Finck                 UDFPrint(("UDFCheckRegValue: couldn't allocate defaultParamPath\n"));
2310*c2c66affSColin Finck                 try_return(val = DefValue);
2311*c2c66affSColin Finck             }
2312*c2c66affSColin Finck 
2313*c2c66affSColin Finck             RtlZeroMemory(defaultParamPath.Buffer, defaultParamPath.MaximumLength);
2314*c2c66affSColin Finck             status = RtlAppendUnicodeToString(&defaultParamPath, paramPath.Buffer);
2315*c2c66affSColin Finck             if(!NT_SUCCESS(status)) {
2316*c2c66affSColin Finck                 try_return(val = DefValue);
2317*c2c66affSColin Finck             }
2318*c2c66affSColin Finck             status = RtlAppendUnicodeToString(&defaultParamPath, defaultParamStr.Buffer);
2319*c2c66affSColin Finck             if(!NT_SUCCESS(status)) {
2320*c2c66affSColin Finck                 try_return(val = DefValue);
2321*c2c66affSColin Finck             }
2322*c2c66affSColin Finck             UDFPrint(("UDFCheckRegValue: (3) |%S|\n", defaultParamPath.Buffer));
2323*c2c66affSColin Finck         }
2324*c2c66affSColin Finck 
2325*c2c66affSColin Finck         if(PtrVolumePath) {
2326*c2c66affSColin Finck             paramSuffix = *PtrVolumePath;
2327*c2c66affSColin Finck         } else {
2328*c2c66affSColin Finck             RtlInitUnicodeString(&paramSuffix, NULL);
2329*c2c66affSColin Finck         }
2330*c2c66affSColin Finck 
2331*c2c66affSColin Finck         RtlInitUnicodeString(&paramDevPath, NULL);
2332*c2c66affSColin Finck         // now build the device specific path
2333*c2c66affSColin Finck         paramDevPath.MaximumLength = paramPath.Length + paramSuffix.Length + sizeof(WCHAR);
2334*c2c66affSColin Finck         paramDevPath.Buffer = (PWCH)MyAllocatePool__(PagedPool, paramDevPath.MaximumLength);
2335*c2c66affSColin Finck         if(!paramDevPath.Buffer) {
2336*c2c66affSColin Finck             try_return(val = DefValue);
2337*c2c66affSColin Finck         }
2338*c2c66affSColin Finck 
2339*c2c66affSColin Finck         RtlZeroMemory(paramDevPath.Buffer, paramDevPath.MaximumLength);
2340*c2c66affSColin Finck         status = RtlAppendUnicodeToString(&paramDevPath, paramPath.Buffer);
2341*c2c66affSColin Finck         if(!NT_SUCCESS(status)) {
2342*c2c66affSColin Finck             try_return(val = DefValue);
2343*c2c66affSColin Finck         }
2344*c2c66affSColin Finck         if(paramSuffix.Buffer) {
2345*c2c66affSColin Finck             status = RtlAppendUnicodeToString(&paramDevPath, paramSuffix.Buffer);
2346*c2c66affSColin Finck             if(!NT_SUCCESS(status)) {
2347*c2c66affSColin Finck                 try_return(val = DefValue);
2348*c2c66affSColin Finck             }
2349*c2c66affSColin Finck         }
2350*c2c66affSColin Finck 
2351*c2c66affSColin Finck         UDFPrint(( " Parameter = %ws\n", Name));
2352*c2c66affSColin Finck 
2353*c2c66affSColin Finck         {
2354*c2c66affSColin Finck             HKEY hk = NULL;
2355*c2c66affSColin Finck             status = RegTGetKeyHandle(NULL, RegistryPath->Buffer, &hk);
2356*c2c66affSColin Finck             if(NT_SUCCESS(status)) {
2357*c2c66affSColin Finck                 RegTCloseKeyHandle(hk);
2358*c2c66affSColin Finck             }
2359*c2c66affSColin Finck         }
2360*c2c66affSColin Finck 
2361*c2c66affSColin Finck 
2362*c2c66affSColin Finck         // *** Read GLOBAL_DEFAULTS from
2363*c2c66affSColin Finck         // "\DwUdf\Parameters_Unknown\"
2364*c2c66affSColin Finck 
2365*c2c66affSColin Finck         status = RegTGetDwordValue(NULL, paramPath.Buffer, Name, &val);
2366*c2c66affSColin Finck 
2367*c2c66affSColin Finck         // *** Read DEV_CLASS_SPEC_DEFAULTS (if any) from
2368*c2c66affSColin Finck         // "\DwUdf\Parameters_%DevClass%\"
2369*c2c66affSColin Finck 
2370*c2c66affSColin Finck         if(DefaultPath) {
2371*c2c66affSColin Finck             status = RegTGetDwordValue(NULL, defaultParamPath.Buffer, Name, &val);
2372*c2c66affSColin Finck         }
2373*c2c66affSColin Finck 
2374*c2c66affSColin Finck         // *** Read DEV_SPEC_PARAMS from (if device supports GetDevName)
2375*c2c66affSColin Finck         // "\DwUdf\Parameters\%DevName%\"
2376*c2c66affSColin Finck 
2377*c2c66affSColin Finck         status = RegTGetDwordValue(NULL, paramDevPath.Buffer, Name, &val);
2378*c2c66affSColin Finck 
2379*c2c66affSColin Finck try_exit:   NOTHING;
2380*c2c66affSColin Finck 
2381*c2c66affSColin Finck     } _SEH2_FINALLY {
2382*c2c66affSColin Finck 
2383*c2c66affSColin Finck         if(DefaultPath && defaultParamPath.Buffer) {
2384*c2c66affSColin Finck             MyFreePool__(defaultParamPath.Buffer);
2385*c2c66affSColin Finck         }
2386*c2c66affSColin Finck         if(paramPath.Buffer) {
2387*c2c66affSColin Finck             MyFreePool__(paramPath.Buffer);
2388*c2c66affSColin Finck         }
2389*c2c66affSColin Finck         if(paramDevPath.Buffer) {
2390*c2c66affSColin Finck             MyFreePool__(paramDevPath.Buffer);
2391*c2c66affSColin Finck         }
2392*c2c66affSColin Finck         if(paramPathUnknown.Buffer) {
2393*c2c66affSColin Finck             MyFreePool__(paramPathUnknown.Buffer);
2394*c2c66affSColin Finck         }
2395*c2c66affSColin Finck     } _SEH2_END;
2396*c2c66affSColin Finck 
2397*c2c66affSColin Finck     UDFPrint(( "UDFCheckRegValue: %ws for drive %s is %x\n\n", Name, PtrVolumePath, val));
2398*c2c66affSColin Finck     return val;
2399*c2c66affSColin Finck } // end UDFRegCheckParameterValue()
2400*c2c66affSColin Finck 
2401*c2c66affSColin Finck /*
2402*c2c66affSColin Finck Routine Description:
2403*c2c66affSColin Finck     This routine is called to initialize an IrpContext for the current
2404*c2c66affSColin Finck     UDFFS request.  The IrpContext is on the stack and we need to initialize
2405*c2c66affSColin Finck     it for the current request.  The request is a close operation.
2406*c2c66affSColin Finck 
2407*c2c66affSColin Finck Arguments:
2408*c2c66affSColin Finck 
2409*c2c66affSColin Finck     IrpContext - IrpContext to initialize.
2410*c2c66affSColin Finck 
2411*c2c66affSColin Finck     IrpContextLite - source for initialization
2412*c2c66affSColin Finck 
2413*c2c66affSColin Finck Return Value:
2414*c2c66affSColin Finck 
2415*c2c66affSColin Finck     None
2416*c2c66affSColin Finck 
2417*c2c66affSColin Finck */
2418*c2c66affSColin Finck VOID
UDFInitializeIrpContextFromLite(OUT PtrUDFIrpContext * IrpContext,IN PtrUDFIrpContextLite IrpContextLite)2419*c2c66affSColin Finck UDFInitializeIrpContextFromLite(
2420*c2c66affSColin Finck     OUT PtrUDFIrpContext    *IrpContext,
2421*c2c66affSColin Finck     IN PtrUDFIrpContextLite IrpContextLite
2422*c2c66affSColin Finck     )
2423*c2c66affSColin Finck {
2424*c2c66affSColin Finck     (*IrpContext) = UDFAllocateIrpContext(NULL, IrpContextLite->RealDevice);
2425*c2c66affSColin Finck     //  Zero and then initialize the structure.
2426*c2c66affSColin Finck 
2427*c2c66affSColin Finck     //  Major/Minor Function codes
2428*c2c66affSColin Finck     (*IrpContext)->MajorFunction = IRP_MJ_CLOSE;
2429*c2c66affSColin Finck     (*IrpContext)->Fcb = IrpContextLite->Fcb;
2430*c2c66affSColin Finck     (*IrpContext)->TreeLength = IrpContextLite->TreeLength;
2431*c2c66affSColin Finck     (*IrpContext)->IrpContextFlags |= (IrpContextLite->IrpContextFlags & ~UDF_IRP_CONTEXT_NOT_FROM_ZONE);
2432*c2c66affSColin Finck 
2433*c2c66affSColin Finck     //  Set the wait parameter
2434*c2c66affSColin Finck     UDFSetFlag( (*IrpContext)->IrpContextFlags, UDF_IRP_CONTEXT_CAN_BLOCK );
2435*c2c66affSColin Finck 
2436*c2c66affSColin Finck     return;
2437*c2c66affSColin Finck } // end UDFInitializeIrpContextFromLite()
2438*c2c66affSColin Finck 
2439*c2c66affSColin Finck /*
2440*c2c66affSColin Finck Routine Description:
2441*c2c66affSColin Finck     This routine is called to initialize an IrpContext for the current
2442*c2c66affSColin Finck     UDFFS request.  The IrpContext is on the stack and we need to initialize
2443*c2c66affSColin Finck     it for the current request.  The request is a close operation.
2444*c2c66affSColin Finck 
2445*c2c66affSColin Finck Arguments:
2446*c2c66affSColin Finck 
2447*c2c66affSColin Finck     IrpContext - IrpContext to initialize.
2448*c2c66affSColin Finck 
2449*c2c66affSColin Finck     IrpContextLite - source for initialization
2450*c2c66affSColin Finck 
2451*c2c66affSColin Finck Return Value:
2452*c2c66affSColin Finck 
2453*c2c66affSColin Finck     None
2454*c2c66affSColin Finck 
2455*c2c66affSColin Finck */
2456*c2c66affSColin Finck NTSTATUS
UDFInitializeIrpContextLite(OUT PtrUDFIrpContextLite * IrpContextLite,IN PtrUDFIrpContext IrpContext,IN PtrUDFFCB Fcb)2457*c2c66affSColin Finck UDFInitializeIrpContextLite(
2458*c2c66affSColin Finck     OUT PtrUDFIrpContextLite *IrpContextLite,
2459*c2c66affSColin Finck     IN PtrUDFIrpContext    IrpContext,
2460*c2c66affSColin Finck     IN PtrUDFFCB           Fcb
2461*c2c66affSColin Finck     )
2462*c2c66affSColin Finck {
2463*c2c66affSColin Finck     PtrUDFIrpContextLite LocalIrpContextLite = (PtrUDFIrpContextLite)MyAllocatePool__(NonPagedPool,sizeof(UDFIrpContextLite));
2464*c2c66affSColin Finck     if(!LocalIrpContextLite)
2465*c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
2466*c2c66affSColin Finck     //  Zero and then initialize the structure.
2467*c2c66affSColin Finck     RtlZeroMemory( LocalIrpContextLite, sizeof( UDFIrpContextLite ));
2468*c2c66affSColin Finck 
2469*c2c66affSColin Finck     LocalIrpContextLite->NodeIdentifier.NodeType  = UDF_NODE_TYPE_IRP_CONTEXT_LITE;
2470*c2c66affSColin Finck     LocalIrpContextLite->NodeIdentifier.NodeSize  = sizeof(UDFIrpContextLite);
2471*c2c66affSColin Finck 
2472*c2c66affSColin Finck     LocalIrpContextLite->Fcb = Fcb;
2473*c2c66affSColin Finck     LocalIrpContextLite->TreeLength = IrpContext->TreeLength;
2474*c2c66affSColin Finck     //  Copy RealDevice for workque algorithms.
2475*c2c66affSColin Finck     LocalIrpContextLite->RealDevice = IrpContext->TargetDeviceObject;
2476*c2c66affSColin Finck     LocalIrpContextLite->IrpContextFlags = IrpContext->IrpContextFlags;
2477*c2c66affSColin Finck     *IrpContextLite = LocalIrpContextLite;
2478*c2c66affSColin Finck 
2479*c2c66affSColin Finck     return STATUS_SUCCESS;
2480*c2c66affSColin Finck } // end UDFInitializeIrpContextLite()
2481*c2c66affSColin Finck 
2482*c2c66affSColin Finck NTSTATUS
2483*c2c66affSColin Finck NTAPI
UDFQuerySetEA(PDEVICE_OBJECT DeviceObject,PIRP Irp)2484*c2c66affSColin Finck UDFQuerySetEA(
2485*c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject,       // the logical volume device object
2486*c2c66affSColin Finck     PIRP           Irp                 // I/O Request Packet
2487*c2c66affSColin Finck     )
2488*c2c66affSColin Finck {
2489*c2c66affSColin Finck     NTSTATUS         RC = STATUS_SUCCESS;
2490*c2c66affSColin Finck //    PtrUDFIrpContext PtrIrpContext = NULL;
2491*c2c66affSColin Finck     BOOLEAN          AreWeTopLevel = FALSE;
2492*c2c66affSColin Finck 
2493*c2c66affSColin Finck     UDFPrint(("UDFQuerySetEA: \n"));
2494*c2c66affSColin Finck 
2495*c2c66affSColin Finck     FsRtlEnterFileSystem();
2496*c2c66affSColin Finck     ASSERT(DeviceObject);
2497*c2c66affSColin Finck     ASSERT(Irp);
2498*c2c66affSColin Finck 
2499*c2c66affSColin Finck     // set the top level context
2500*c2c66affSColin Finck     AreWeTopLevel = UDFIsIrpTopLevel(Irp);
2501*c2c66affSColin Finck 
2502*c2c66affSColin Finck     RC = STATUS_EAS_NOT_SUPPORTED;
2503*c2c66affSColin Finck     Irp->IoStatus.Status = RC;
2504*c2c66affSColin Finck     Irp->IoStatus.Information = 0;
2505*c2c66affSColin Finck     // complete the IRP
2506*c2c66affSColin Finck     IoCompleteRequest(Irp, IO_DISK_INCREMENT);
2507*c2c66affSColin Finck 
2508*c2c66affSColin Finck     if(AreWeTopLevel) {
2509*c2c66affSColin Finck         IoSetTopLevelIrp(NULL);
2510*c2c66affSColin Finck     }
2511*c2c66affSColin Finck 
2512*c2c66affSColin Finck     FsRtlExitFileSystem();
2513*c2c66affSColin Finck 
2514*c2c66affSColin Finck     return(RC);
2515*c2c66affSColin Finck } // end UDFQuerySetEA()
2516*c2c66affSColin Finck 
2517*c2c66affSColin Finck ULONG
UDFIsResourceAcquired(IN PERESOURCE Resource)2518*c2c66affSColin Finck UDFIsResourceAcquired(
2519*c2c66affSColin Finck     IN PERESOURCE Resource
2520*c2c66affSColin Finck     )
2521*c2c66affSColin Finck {
2522*c2c66affSColin Finck     ULONG ReAcqRes =
2523*c2c66affSColin Finck         ExIsResourceAcquiredExclusiveLite(Resource) ? 1 :
2524*c2c66affSColin Finck         (ExIsResourceAcquiredSharedLite(Resource) ? 2 : 0);
2525*c2c66affSColin Finck     return ReAcqRes;
2526*c2c66affSColin Finck } // end UDFIsResourceAcquired()
2527*c2c66affSColin Finck 
2528*c2c66affSColin Finck BOOLEAN
UDFAcquireResourceExclusiveWithCheck(IN PERESOURCE Resource)2529*c2c66affSColin Finck UDFAcquireResourceExclusiveWithCheck(
2530*c2c66affSColin Finck     IN PERESOURCE Resource
2531*c2c66affSColin Finck     )
2532*c2c66affSColin Finck {
2533*c2c66affSColin Finck     ULONG ReAcqRes =
2534*c2c66affSColin Finck         ExIsResourceAcquiredExclusiveLite(Resource) ? 1 :
2535*c2c66affSColin Finck         (ExIsResourceAcquiredSharedLite(Resource) ? 2 : 0);
2536*c2c66affSColin Finck     if(ReAcqRes) {
2537*c2c66affSColin Finck         UDFPrint(("UDFAcquireResourceExclusiveWithCheck: ReAcqRes, %x\n", ReAcqRes));
2538*c2c66affSColin Finck     } else {
2539*c2c66affSColin Finck //        BrutePoint();
2540*c2c66affSColin Finck     }
2541*c2c66affSColin Finck 
2542*c2c66affSColin Finck     if(ReAcqRes == 1) {
2543*c2c66affSColin Finck         // OK
2544*c2c66affSColin Finck     } else
2545*c2c66affSColin Finck     if(ReAcqRes == 2) {
2546*c2c66affSColin Finck         UDFPrint(("UDFAcquireResourceExclusiveWithCheck: !!! Shared !!!\n"));
2547*c2c66affSColin Finck         //BrutePoint();
2548*c2c66affSColin Finck     } else {
2549*c2c66affSColin Finck         UDFAcquireResourceExclusive(Resource, TRUE);
2550*c2c66affSColin Finck         return TRUE;
2551*c2c66affSColin Finck     }
2552*c2c66affSColin Finck     return FALSE;
2553*c2c66affSColin Finck } // end UDFAcquireResourceExclusiveWithCheck()
2554*c2c66affSColin Finck 
2555*c2c66affSColin Finck BOOLEAN
UDFAcquireResourceSharedWithCheck(IN PERESOURCE Resource)2556*c2c66affSColin Finck UDFAcquireResourceSharedWithCheck(
2557*c2c66affSColin Finck     IN PERESOURCE Resource
2558*c2c66affSColin Finck     )
2559*c2c66affSColin Finck {
2560*c2c66affSColin Finck     ULONG ReAcqRes =
2561*c2c66affSColin Finck         ExIsResourceAcquiredExclusiveLite(Resource) ? 1 :
2562*c2c66affSColin Finck         (ExIsResourceAcquiredSharedLite(Resource) ? 2 : 0);
2563*c2c66affSColin Finck     if(ReAcqRes) {
2564*c2c66affSColin Finck         UDFPrint(("UDFAcquireResourceSharedWithCheck: ReAcqRes, %x\n", ReAcqRes));
2565*c2c66affSColin Finck /*    } else {
2566*c2c66affSColin Finck         BrutePoint();*/
2567*c2c66affSColin Finck     }
2568*c2c66affSColin Finck 
2569*c2c66affSColin Finck     if(ReAcqRes == 2) {
2570*c2c66affSColin Finck         // OK
2571*c2c66affSColin Finck     } else
2572*c2c66affSColin Finck     if(ReAcqRes == 1) {
2573*c2c66affSColin Finck         UDFPrint(("UDFAcquireResourceSharedWithCheck: Exclusive\n"));
2574*c2c66affSColin Finck         //BrutePoint();
2575*c2c66affSColin Finck     } else {
2576*c2c66affSColin Finck         UDFAcquireResourceShared(Resource, TRUE);
2577*c2c66affSColin Finck         return TRUE;
2578*c2c66affSColin Finck     }
2579*c2c66affSColin Finck     return FALSE;
2580*c2c66affSColin Finck } // end UDFAcquireResourceSharedWithCheck()
2581*c2c66affSColin Finck 
2582*c2c66affSColin Finck NTSTATUS
UDFWCacheErrorHandler(IN PVOID Context,IN PWCACHE_ERROR_CONTEXT ErrorInfo)2583*c2c66affSColin Finck UDFWCacheErrorHandler(
2584*c2c66affSColin Finck     IN PVOID Context,
2585*c2c66affSColin Finck     IN PWCACHE_ERROR_CONTEXT ErrorInfo
2586*c2c66affSColin Finck     )
2587*c2c66affSColin Finck {
2588*c2c66affSColin Finck     InterlockedIncrement((PLONG)&(((PVCB)Context)->IoErrorCounter));
2589*c2c66affSColin Finck     return ErrorInfo->Status;
2590*c2c66affSColin Finck }
2591*c2c66affSColin Finck 
2592*c2c66affSColin Finck #include "Include/misc_common.cpp"
2593*c2c66affSColin Finck #include "Include/regtools.cpp"
2594*c2c66affSColin Finck 
2595