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(¶mStr, L"\\Parameters");
2257*c2c66affSColin Finck RtlInitUnicodeString(¶mPath, NULL);
2258*c2c66affSColin Finck
2259*c2c66affSColin Finck RtlInitUnicodeString(¶mPathUnknownStr, REG_DEFAULT_UNKNOWN);
2260*c2c66affSColin Finck RtlInitUnicodeString(¶mPathUnknown, 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(¶mPath, RegistryPath->Buffer);
2278*c2c66affSColin Finck if(!NT_SUCCESS(status)) {
2279*c2c66affSColin Finck try_return(val = DefValue);
2280*c2c66affSColin Finck }
2281*c2c66affSColin Finck status = RtlAppendUnicodeToString(¶mPath, 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(¶mPathUnknown, RegistryPath->Buffer);
2289*c2c66affSColin Finck if(!NT_SUCCESS(status)) {
2290*c2c66affSColin Finck try_return(val = DefValue);
2291*c2c66affSColin Finck }
2292*c2c66affSColin Finck status = RtlAppendUnicodeToString(¶mPathUnknown, paramStr.Buffer);
2293*c2c66affSColin Finck if(!NT_SUCCESS(status)) {
2294*c2c66affSColin Finck try_return(val = DefValue);
2295*c2c66affSColin Finck }
2296*c2c66affSColin Finck status = RtlAppendUnicodeToString(¶mPathUnknown, 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(¶mSuffix, NULL);
2329*c2c66affSColin Finck }
2330*c2c66affSColin Finck
2331*c2c66affSColin Finck RtlInitUnicodeString(¶mDevPath, 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(¶mDevPath, 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(¶mDevPath, 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