Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmisc.c
Go to the documentation of this file.
00001 /************************************************************************* 00002 * 00003 * File: misc.c 00004 * 00005 * Module: Ext2 File System Driver (Kernel mode execution only) 00006 * 00007 * Description: 00008 * This file contains some miscellaneous support routines. 00009 * 00010 * Author: Manoj Paul Joseph 00011 * 00012 * 00013 *************************************************************************/ 00014 00015 #include "ext2fsd.h" 00016 00017 // define the file specific bug-check id 00018 #define EXT2_BUG_CHECK_ID EXT2_FILE_MISC 00019 00020 #define DEBUG_LEVEL ( DEBUG_TRACE_MISC ) 00021 00022 /************************************************************************* 00023 * 00024 * Function: Ext2InitializeZones() 00025 * 00026 * Description: 00027 * Allocates some memory for global zones used to allocate FSD structures. 00028 * Either all memory will be allocated or we will back out gracefully. 00029 * 00030 * Expected Interrupt Level (for execution) : 00031 * 00032 * IRQL_PASSIVE_LEVEL 00033 * 00034 * Return Value: STATUS_SUCCESS/Error 00035 * 00036 *************************************************************************/ 00037 NTSTATUS NTAPI Ext2InitializeZones( 00038 void) 00039 { 00040 NTSTATUS RC = STATUS_SUCCESS; 00041 uint32 SizeOfZone = Ext2GlobalData.DefaultZoneSizeInNumStructs; 00042 uint32 SizeOfObjectNameZone = 0; 00043 uint32 SizeOfCCBZone = 0; 00044 uint32 SizeOfFCBZone = 0; 00045 uint32 SizeOfByteLockZone = 0; 00046 uint32 SizeOfIrpContextZone = 0; 00047 00048 try { 00049 00050 // initialize the spinlock protecting the zones 00051 KeInitializeSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock)); 00052 00053 // determine memory requirements 00054 switch (MmQuerySystemSize()) { 00055 case MmSmallSystem: 00056 // this is just for illustration purposes. I will multiply 00057 // number of structures with some arbitrary amount depending 00058 // upon available memory in the system ... You should choose a 00059 // more intelligent method suitable to your memory consumption 00060 // and the amount of memory available. 00061 SizeOfObjectNameZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER); 00062 SizeOfCCBZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER); 00063 SizeOfFCBZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER); 00064 SizeOfByteLockZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER); 00065 SizeOfIrpContextZone = (2 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER); 00066 break; 00067 case MmMediumSystem: 00068 SizeOfObjectNameZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER); 00069 SizeOfCCBZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER); 00070 SizeOfFCBZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER); 00071 SizeOfByteLockZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER); 00072 SizeOfIrpContextZone = (4 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER); 00073 break; 00074 case MmLargeSystem: 00075 SizeOfObjectNameZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2ObjectName))) + sizeof(ZONE_SEGMENT_HEADER); 00076 SizeOfCCBZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2CCB))) + sizeof(ZONE_SEGMENT_HEADER); 00077 SizeOfFCBZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FCB))) + sizeof(ZONE_SEGMENT_HEADER); 00078 SizeOfByteLockZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2FileLockInfo))) + sizeof(ZONE_SEGMENT_HEADER); 00079 SizeOfIrpContextZone = (8 * SizeOfZone * Ext2QuadAlign(sizeof(Ext2IrpContext))) + sizeof(ZONE_SEGMENT_HEADER); 00080 break; 00081 } 00082 00083 // typical NT methodology (at least until *someone* exposed the "difference" between a server and workstation ;-) 00084 if (MmIsThisAnNtAsSystem()) { 00085 SizeOfObjectNameZone *= EXT2_NTAS_MULTIPLE; 00086 SizeOfCCBZone *= EXT2_NTAS_MULTIPLE; 00087 SizeOfFCBZone *= EXT2_NTAS_MULTIPLE; 00088 SizeOfByteLockZone *= EXT2_NTAS_MULTIPLE; 00089 SizeOfIrpContextZone *= EXT2_NTAS_MULTIPLE; 00090 } 00091 00092 // allocate memory for each of the zones and initialize the zones ... 00093 if (!(Ext2GlobalData.ObjectNameZone = Ext2AllocatePool(NonPagedPool, SizeOfObjectNameZone ))) { 00094 RC = STATUS_INSUFFICIENT_RESOURCES; 00095 try_return(); 00096 } 00097 00098 if (!(Ext2GlobalData.CCBZone = Ext2AllocatePool(NonPagedPool, SizeOfCCBZone ))) { 00099 RC = STATUS_INSUFFICIENT_RESOURCES; 00100 try_return(); 00101 } 00102 00103 if (!(Ext2GlobalData.FCBZone = Ext2AllocatePool(NonPagedPool, SizeOfFCBZone ))) { 00104 RC = STATUS_INSUFFICIENT_RESOURCES; 00105 try_return(); 00106 } 00107 00108 if (!(Ext2GlobalData.ByteLockZone = Ext2AllocatePool(NonPagedPool, SizeOfByteLockZone ))) { 00109 RC = STATUS_INSUFFICIENT_RESOURCES; 00110 try_return(); 00111 } 00112 00113 if (!(Ext2GlobalData.IrpContextZone = Ext2AllocatePool(NonPagedPool, SizeOfIrpContextZone ))) { 00114 RC = STATUS_INSUFFICIENT_RESOURCES; 00115 try_return(); 00116 } 00117 00118 // initialize each of the zone headers ... 00119 if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.ObjectNameZoneHeader), 00120 Ext2QuadAlign(sizeof(Ext2ObjectName)), 00121 Ext2GlobalData.ObjectNameZone, SizeOfObjectNameZone))) { 00122 // failed the initialization, leave ... 00123 try_return(); 00124 } 00125 00126 if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.CCBZoneHeader), 00127 Ext2QuadAlign(sizeof(Ext2CCB)), 00128 Ext2GlobalData.CCBZone, 00129 SizeOfCCBZone))) { 00130 // failed the initialization, leave ... 00131 try_return(); 00132 } 00133 00134 if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.FCBZoneHeader), 00135 Ext2QuadAlign(sizeof(Ext2FCB)), 00136 Ext2GlobalData.FCBZone, 00137 SizeOfFCBZone))) { 00138 // failed the initialization, leave ... 00139 try_return(); 00140 } 00141 00142 if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.ByteLockZoneHeader), 00143 Ext2QuadAlign(sizeof(Ext2FileLockInfo)), 00144 Ext2GlobalData.ByteLockZone, 00145 SizeOfByteLockZone))) { 00146 // failed the initialization, leave ... 00147 try_return(); 00148 } 00149 00150 if (!NT_SUCCESS(RC = ExInitializeZone(&(Ext2GlobalData.IrpContextZoneHeader), 00151 Ext2QuadAlign(sizeof(Ext2IrpContext)), 00152 Ext2GlobalData.IrpContextZone, 00153 SizeOfIrpContextZone))) { 00154 // failed the initialization, leave ... 00155 try_return(); 00156 } 00157 00158 try_exit: NOTHING; 00159 00160 } finally { 00161 if (!NT_SUCCESS(RC)) { 00162 // invoke the destroy routine now ... 00163 Ext2DestroyZones(); 00164 } else { 00165 // mark the fact that we have allocated zones ... 00166 Ext2SetFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_ZONES_INITIALIZED); 00167 } 00168 } 00169 00170 return(RC); 00171 } 00172 00173 00174 /************************************************************************* 00175 * 00176 * Function: Ext2DestroyZones() 00177 * 00178 * Description: 00179 * Free up the previously allocated memory. NEVER do this once the 00180 * driver has been successfully loaded. 00181 * 00182 * Expected Interrupt Level (for execution) : 00183 * 00184 * IRQL_PASSIVE_LEVEL 00185 * 00186 * Return Value: None 00187 * 00188 *************************************************************************/ 00189 void NTAPI Ext2DestroyZones( 00190 void) 00191 { 00192 try { 00193 // free up each of the pools 00194 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.ObjectNameZone); 00195 ExFreePool(Ext2GlobalData.ObjectNameZone); 00196 00197 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.CCBZone); 00198 ExFreePool(Ext2GlobalData.CCBZone); 00199 00200 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.FCBZone); 00201 ExFreePool(Ext2GlobalData.FCBZone); 00202 00203 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.ByteLockZone); 00204 ExFreePool(Ext2GlobalData.ByteLockZone); 00205 00206 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", Ext2GlobalData.IrpContextZone); 00207 ExFreePool(Ext2GlobalData.IrpContextZone); 00208 } 00209 finally 00210 { 00211 Ext2ClearFlag(Ext2GlobalData.Ext2Flags, EXT2_DATA_FLAGS_ZONES_INITIALIZED); 00212 } 00213 00214 return; 00215 } 00216 00217 00218 /************************************************************************* 00219 * 00220 * Function: Ext2IsIrpTopLevel() 00221 * 00222 * Description: 00223 * Helps the FSD determine who the "top level" caller is for this 00224 * request. A request can originate directly from a user process 00225 * (in which case, the "top level" will be NULL when this routine 00226 * is invoked), OR the user may have originated either from the NT 00227 * Cache Manager/VMM ("top level" may be set), or this could be a 00228 * recursion into our code in which we would have set the "top level" 00229 * field the last time around. 00230 * 00231 * Expected Interrupt Level (for execution) : 00232 * 00233 * whatever level a particular dispatch routine is invoked at. 00234 * 00235 * Return Value: TRUE/FALSE (TRUE if top level was NULL when routine invoked) 00236 * 00237 *************************************************************************/ 00238 BOOLEAN NTAPI Ext2IsIrpTopLevel( 00239 PIRP Irp) // the IRP sent to our dispatch routine 00240 { 00241 BOOLEAN ReturnCode = FALSE; 00242 00243 if (IoGetTopLevelIrp() == NULL) 00244 { 00245 // OK, so we can set ourselves to become the "top level" component 00246 IoSetTopLevelIrp( Irp ); 00247 ReturnCode = TRUE; 00248 } 00249 00250 return(ReturnCode); 00251 } 00252 00253 00254 /************************************************************************* 00255 * 00256 * Function: Ext2ExceptionFilter() 00257 * 00258 * Description: 00259 * This routines allows the driver to determine whether the exception 00260 * is an "allowed" exception i.e. one we should not-so-quietly consume 00261 * ourselves, or one which should be propagated onwards in which case 00262 * we will most likely bring down the machine. 00263 * 00264 * This routine employs the services of FsRtlIsNtstatusExpected(). This 00265 * routine returns a BOOLEAN result. A RC of FALSE will cause us to return 00266 * EXCEPTION_CONTINUE_SEARCH which will probably cause a panic. 00267 * The FsRtl.. routine returns FALSE iff exception values are (currently) : 00268 * STATUS_DATATYPE_MISALIGNMENT || STATUS_ACCESS_VIOLATION || 00269 * STATUS_ILLEGAL_INSTRUCTION || STATUS_INSTRUCTION_MISALIGNMENT 00270 * 00271 * Expected Interrupt Level (for execution) : 00272 * 00273 * ? 00274 * 00275 * Return Value: EXCEPTION_EXECUTE_HANDLER/EXECEPTION_CONTINUE_SEARCH 00276 * 00277 *************************************************************************/ 00278 long NTAPI Ext2ExceptionFilter( 00279 PtrExt2IrpContext PtrIrpContext, 00280 PEXCEPTION_POINTERS PtrExceptionPointers ) 00281 { 00282 long ReturnCode = EXCEPTION_EXECUTE_HANDLER; 00283 NTSTATUS ExceptionCode = STATUS_SUCCESS; 00284 00285 // figure out the exception code 00286 ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionCode; 00287 00288 if ((ExceptionCode == STATUS_IN_PAGE_ERROR) && (PtrExceptionPointers->ExceptionRecord->NumberParameters >= 3)) 00289 { 00290 ExceptionCode = PtrExceptionPointers->ExceptionRecord->ExceptionInformation[2]; 00291 } 00292 00293 if (PtrIrpContext) 00294 { 00295 PtrIrpContext->SavedExceptionCode = ExceptionCode; 00296 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_EXCEPTION); 00297 } 00298 00299 // check if we should propagate this exception or not 00300 if (!(FsRtlIsNtstatusExpected(ExceptionCode))) 00301 { 00302 // we are not ok, propagate this exception. 00303 // NOTE: we will bring down the machine ... 00304 ReturnCode = EXCEPTION_CONTINUE_SEARCH; 00305 00306 // better free up the IrpContext now ... 00307 if (PtrIrpContext) 00308 { 00309 Ext2ReleaseIrpContext(PtrIrpContext); 00310 } 00311 } 00312 00313 // if you wish to perform some special processing when 00314 // not propagating the exception, set up the state for 00315 // special processing now ... 00316 00317 // return the appropriate code 00318 return(ReturnCode); 00319 } 00320 00321 /************************************************************************* 00322 * 00323 * Function: Ext2ExceptionHandler() 00324 * 00325 * Description: 00326 * One of the routines in the FSD or in the modules we invoked encountered 00327 * an exception. We have decided that we will "handle" the exception. 00328 * Therefore we will prevent the machine from a panic ... 00329 * You can do pretty much anything you choose to in your commercial 00330 * driver at this point to ensure a graceful exit. In the sample 00331 * driver, I will simply free up the IrpContext (if any), set the 00332 * error code in the IRP and complete the IRP at this time ... 00333 * 00334 * Expected Interrupt Level (for execution) : 00335 * 00336 * ? 00337 * 00338 * Return Value: Error code 00339 * 00340 *************************************************************************/ 00341 NTSTATUS NTAPI Ext2ExceptionHandler( 00342 PtrExt2IrpContext PtrIrpContext, 00343 PIRP Irp) 00344 { 00345 NTSTATUS RC; 00346 00347 ASSERT(Irp); 00348 00349 if (PtrIrpContext) 00350 { 00351 RC = PtrIrpContext->SavedExceptionCode; 00352 // Free irp context here 00353 Ext2ReleaseIrpContext(PtrIrpContext); 00354 } 00355 else 00356 { 00357 // must be insufficient resources ...? 00358 RC = STATUS_INSUFFICIENT_RESOURCES; 00359 } 00360 00361 // set the error code in the IRP 00362 Irp->IoStatus.Status = RC; 00363 Irp->IoStatus.Information = 0; 00364 00365 // complete the IRP 00366 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00367 00368 return(RC); 00369 } 00370 00371 /************************************************************************* 00372 * 00373 * Function: Ext2LogEvent() 00374 * 00375 * Description: 00376 * Log a message in the NT Event Log. This is a rather simplistic log 00377 * methodology since you can potentially utilize the event log to 00378 * provide a lot of information to the user (and you should too!) 00379 * 00380 * Expected Interrupt Level (for execution) : 00381 * 00382 * IRQL_PASSIVE_LEVEL 00383 * 00384 * Return Value: None 00385 * 00386 *************************************************************************/ 00387 void NTAPI Ext2LogEvent( 00388 NTSTATUS Ext2EventLogId, // the Ext2 private message id 00389 NTSTATUS RC) // any NT error code we wish to log ... 00390 { 00391 try 00392 { 00393 00394 // Implement a call to IoAllocateErrorLogEntry() followed by a call 00395 // to IoWriteErrorLogEntry(). You should note that the call to IoWriteErrorLogEntry() 00396 // will free memory for the entry once the write completes (which in actuality 00397 // is an asynchronous operation). 00398 00399 } 00400 except (EXCEPTION_EXECUTE_HANDLER) 00401 { 00402 // nothing really we can do here, just do not wish to crash ... 00403 NOTHING; 00404 } 00405 00406 return; 00407 } 00408 00409 /************************************************************************* 00410 * 00411 * Function: Ext2AllocateObjectName() 00412 * 00413 * Description: 00414 * Allocate a new ObjectName structure to represent an open on-disk object. 00415 * Also initialize the ObjectName structure to NULL. 00416 * 00417 * Expected Interrupt Level (for execution) : 00418 * 00419 * IRQL_PASSIVE_LEVEL 00420 * 00421 * Return Value: A pointer to the ObjectName structure OR NULL. 00422 * 00423 *************************************************************************/ 00424 PtrExt2ObjectName NTAPI Ext2AllocateObjectName( 00425 void) 00426 { 00427 PtrExt2ObjectName PtrObjectName = NULL; 00428 BOOLEAN AllocatedFromZone = TRUE; 00429 //KIRQL CurrentIrql; 00430 /* 00431 // first, try to allocate out of the zone 00432 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00433 if (!ExIsFullZone(&(Ext2GlobalData.ObjectNameZoneHeader))) { 00434 // we have enough memory 00435 PtrObjectName = (PtrExt2ObjectName)ExAllocateFromZone(&(Ext2GlobalData.ObjectNameZoneHeader)); 00436 00437 // release the spinlock 00438 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00439 } else { 00440 // release the spinlock 00441 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00442 00443 // if we failed to obtain from the zone, get it directly from the VMM 00444 */ 00445 PtrObjectName = (PtrExt2ObjectName)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2ObjectName)) ); 00446 AllocatedFromZone = FALSE; 00447 /* 00448 } 00449 */ 00450 // if we could not obtain the required memory, bug-check. 00451 // Do NOT do this in your commercial driver, instead handle the error gracefully ... 00452 if (!PtrObjectName) 00453 { 00454 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2ObjectName)), 0); 00455 } 00456 00457 // zero out the allocated memory block 00458 RtlZeroMemory( PtrObjectName, Ext2QuadAlign(sizeof(Ext2ObjectName)) ); 00459 00460 // set up some fields ... 00461 PtrObjectName->NodeIdentifier.NodeType = EXT2_NODE_TYPE_OBJECT_NAME; 00462 PtrObjectName->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2ObjectName)); 00463 00464 00465 if (!AllocatedFromZone) 00466 { 00467 Ext2SetFlag(PtrObjectName->ObjectNameFlags, EXT2_OB_NAME_NOT_FROM_ZONE); 00468 } 00469 00470 return(PtrObjectName); 00471 } 00472 00473 00474 /************************************************************************* 00475 * 00476 * Function: Ext2ReleaseObjectName() 00477 * 00478 * Description: 00479 * Deallocate a previously allocated structure. 00480 * 00481 * Expected Interrupt Level (for execution) : 00482 * 00483 * IRQL_PASSIVE_LEVEL 00484 * 00485 * Return Value: None 00486 * 00487 *************************************************************************/ 00488 void NTAPI Ext2ReleaseObjectName( 00489 PtrExt2ObjectName PtrObjectName) 00490 { 00491 #ifdef USE_ZONES 00492 KIRQL CurrentIrql; 00493 #endif 00494 00495 ASSERT(PtrObjectName); 00496 PtrObjectName->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED; 00497 #ifdef USE_ZONES 00498 00499 // give back memory either to the zone or to the VMM 00500 if (!(PtrObjectName->ObjectNameFlags & EXT2_OB_NAME_NOT_FROM_ZONE)) 00501 { 00502 // back to the zone 00503 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00504 ExFreeToZone(&(Ext2GlobalData.ObjectNameZoneHeader), PtrObjectName); 00505 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00506 } 00507 else 00508 { 00509 #endif 00510 00511 Ext2DeallocateUnicodeString( & PtrObjectName->ObjectName ); 00512 00513 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrObjectName); 00514 ExFreePool(PtrObjectName); 00515 00516 #ifdef USE_ZONES 00517 } 00518 #endif 00519 return; 00520 } 00521 00522 /************************************************************************* 00523 * 00524 * Function: Ext2AllocateCCB() 00525 * 00526 * Description: 00527 * Allocate a new CCB structure to represent an open on-disk object. 00528 * Also initialize the CCB structure to NULL. 00529 * 00530 * Expected Interrupt Level (for execution) : 00531 * 00532 * IRQL_PASSIVE_LEVEL 00533 * 00534 * Return Value: A pointer to the CCB structure OR NULL. 00535 * 00536 *************************************************************************/ 00537 PtrExt2CCB NTAPI Ext2AllocateCCB( 00538 void) 00539 { 00540 PtrExt2CCB PtrCCB = NULL; 00541 BOOLEAN AllocatedFromZone = TRUE; 00542 #ifdef USE_ZONES 00543 KIRQL CurrentIrql; 00544 #endif 00545 00546 00547 #ifdef USE_ZONES 00548 // first, try to allocate out of the zone 00549 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00550 if (!ExIsFullZone(&(Ext2GlobalData.CCBZoneHeader))) 00551 { 00552 // we have enough memory 00553 PtrCCB = (PtrExt2CCB)ExAllocateFromZone(&(Ext2GlobalData.CCBZoneHeader)); 00554 00555 // release the spinlock 00556 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00557 } 00558 else 00559 { 00560 // release the spinlock 00561 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00562 // if we failed to obtain from the zone, get it directly from the VMM 00563 #endif 00564 00565 PtrCCB = (PtrExt2CCB)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2CCB)) ); 00566 AllocatedFromZone = FALSE; 00567 00568 #ifdef USE_ZONES 00569 } 00570 #endif 00571 00572 // if we could not obtain the required memory, bug-check. 00573 // Do NOT do this in your commercial driver, instead handle the error gracefully ... 00574 if (!PtrCCB) 00575 { 00576 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2CCB)), 0); 00577 } 00578 00579 // zero out the allocated memory block 00580 RtlZeroMemory(PtrCCB, Ext2QuadAlign(sizeof(Ext2CCB))); 00581 00582 // set up some fields ... 00583 PtrCCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_CCB; 00584 PtrCCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2CCB)); 00585 00586 00587 if (!AllocatedFromZone) 00588 { 00589 Ext2SetFlag(PtrCCB->CCBFlags, EXT2_CCB_NOT_FROM_ZONE); 00590 } 00591 00592 return(PtrCCB); 00593 } 00594 00595 /************************************************************************* 00596 * 00597 * Function: Ext2ReleaseCCB() 00598 * 00599 * Description: 00600 * Deallocate a previously allocated structure. 00601 * 00602 * Expected Interrupt Level (for execution) : 00603 * 00604 * IRQL_PASSIVE_LEVEL 00605 * 00606 * Return Value: None 00607 * 00608 *************************************************************************/ 00609 void NTAPI Ext2ReleaseCCB( 00610 PtrExt2CCB PtrCCB) 00611 { 00612 #ifdef USE_ZONES 00613 KIRQL CurrentIrql; 00614 #endif 00615 00616 ASSERT( PtrCCB ); 00617 if(PtrCCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_CCB) 00618 { 00619 Ext2Panic( PtrCCB, PtrCCB->NodeIdentifier.NodeType, EXT2_NODE_TYPE_CCB ) ; 00620 } 00621 00622 Ext2DeallocateUnicodeString( &PtrCCB->DirectorySearchPattern ); 00623 Ext2DeallocateUnicodeString( &PtrCCB->AbsolutePathName ); 00624 Ext2DeallocateUnicodeString( &PtrCCB->RenameLinkTargetFileName ); 00625 00626 00627 #ifdef USE_ZONES 00628 00629 // give back memory either to the zone or to the VMM 00630 if (!(PtrCCB->CCBFlags & EXT2_CCB_NOT_FROM_ZONE)) 00631 { 00632 // back to the zone 00633 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00634 ExFreeToZone(&(Ext2GlobalData.CCBZoneHeader), PtrCCB); 00635 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00636 } 00637 else 00638 { 00639 #endif 00640 PtrCCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED; 00641 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrCCB); 00642 ExFreePool(PtrCCB); 00643 00644 #ifdef USE_ZONES 00645 } 00646 #endif 00647 00648 return; 00649 } 00650 00651 /************************************************************************* 00652 * 00653 * Function: Ext2AllocateFCB() 00654 * 00655 * Description: 00656 * Allocate a new FCB structure to represent an open on-disk object. 00657 * Also initialize the FCB structure to NULL. 00658 * 00659 * Expected Interrupt Level (for execution) : 00660 * 00661 * IRQL_PASSIVE_LEVEL 00662 * 00663 * Return Value: A pointer to the FCB structure OR NULL. 00664 * 00665 *************************************************************************/ 00666 PtrExt2FCB NTAPI Ext2AllocateFCB( 00667 void) 00668 { 00669 PtrExt2FCB PtrFCB = NULL; 00670 BOOLEAN AllocatedFromZone = TRUE; 00671 #ifdef USE_ZONES 00672 KIRQL CurrentIrql; 00673 #endif 00674 00675 // first, try to allocate out of the zone 00676 #ifdef USE_ZONES 00677 00678 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00679 if (!ExIsFullZone(&(Ext2GlobalData.FCBZoneHeader))) { 00680 // we have enough memory 00681 PtrFCB = (PtrExt2FCB)ExAllocateFromZone(&(Ext2GlobalData.FCBZoneHeader)); 00682 00683 // release the spinlock 00684 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00685 } else { 00686 // release the spinlock 00687 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00688 #endif 00689 // if we failed to obtain from the zone, get it directly from the VMM 00690 PtrFCB = (PtrExt2FCB)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2FCB)) ); 00691 AllocatedFromZone = FALSE; 00692 00693 #ifdef USE_ZONES 00694 } 00695 #endif 00696 00697 // if we could not obtain the required memory, bug-check. 00698 // Do NOT do this in your commercial driver, instead handle the error gracefully ... 00699 if (!PtrFCB) 00700 { 00701 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2FCB)), 0); 00702 } 00703 00704 // zero out the allocated memory block 00705 RtlZeroMemory(PtrFCB, Ext2QuadAlign(sizeof(Ext2FCB))); 00706 00707 // set up some fields ... 00708 PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FCB; 00709 PtrFCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2FCB)); 00710 00711 00712 if (!AllocatedFromZone) 00713 { 00714 Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE); 00715 } 00716 00717 return(PtrFCB); 00718 } 00719 00720 00721 /************************************************************************* 00722 * 00723 * Function: Ext2CreateNewFCB() 00724 * 00725 * Description: 00726 * We want to create a new FCB. We will also create a new CCB (presumably) 00727 * later. Simply allocate a new FCB structure and initialize fields 00728 * appropriately. 00729 * This function also takes the file size values that the caller must 00730 * have obtained and will set the file size fields appropriately in the 00731 * CommonFCBHeader. 00732 * Finally, this routine will initialize the FileObject structure passed 00733 * in to this function. If you decide to fail the call later, remember 00734 * to uninitialize the fields. 00735 * 00736 * Expected Interrupt Level (for execution) : 00737 * 00738 * IRQL_PASSIVE_LEVEL 00739 * 00740 * Return Value: A pointer to the FCB structure OR NULL. 00741 * 00742 *************************************************************************/ 00743 NTSTATUS NTAPI Ext2CreateNewFCB( 00744 PtrExt2FCB *ReturnedFCB, 00745 LARGE_INTEGER AllocationSize, 00746 LARGE_INTEGER EndOfFile, 00747 PFILE_OBJECT PtrFileObject, 00748 PtrExt2VCB PtrVCB, 00749 PtrExt2ObjectName PtrObjectName) 00750 { 00751 NTSTATUS RC = STATUS_SUCCESS; 00752 00753 PtrExt2FCB PtrFCB = NULL; 00754 PtrExt2NTRequiredFCB PtrReqdFCB = NULL; 00755 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader = NULL; 00756 00757 ASSERT( PtrVCB ); 00758 00759 try 00760 { 00761 if( !PtrFileObject ) 00762 { 00763 PtrFCB = Ext2GetUsedFCB( PtrVCB ); 00764 00765 } 00766 else 00767 { 00768 // Obtain a new FCB structure. 00769 // The function Ext2AllocateFCB() will obtain a new structure either 00770 // from a zone or from memory requested directly from the VMM. 00771 PtrFCB = Ext2AllocateFCB(); 00772 } 00773 if (!PtrFCB) 00774 { 00775 // Assume lack of memory. 00776 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 00777 } 00778 00779 // Initialize fields required to interface with the NT Cache Manager. 00780 // Note that the returned structure has already been zeroed. This means 00781 // that the SectionObject structure has been zeroed which is a 00782 // requirement for newly created FCB structures. 00783 PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 00784 00785 // Initialize the MainResource and PagingIoResource structures now. 00786 ExInitializeResourceLite(&(PtrReqdFCB->MainResource)); 00787 Ext2SetFlag(PtrFCB->FCBFlags, EXT2_INITIALIZED_MAIN_RESOURCE); 00788 00789 ExInitializeResourceLite(&(PtrReqdFCB->PagingIoResource)); 00790 Ext2SetFlag(PtrFCB->FCBFlags, EXT2_INITIALIZED_PAGING_IO_RESOURCE); 00791 00792 // Start initializing the fields contained in the CommonFCBHeader. 00793 PtrCommonFCBHeader = &(PtrReqdFCB->CommonFCBHeader); 00794 00795 // Disallow fast-IO for now. 00796 PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible; 00797 00798 // Initialize the MainResource and PagingIoResource pointers in 00799 // the CommonFCBHeader structure to point to the ERESOURCE structures we 00800 // have allocated and already initialized above. 00801 PtrCommonFCBHeader->Resource = &(PtrReqdFCB->MainResource); 00802 PtrCommonFCBHeader->PagingIoResource = &(PtrReqdFCB->PagingIoResource); 00803 00804 // Ignore the Flags field in the CommonFCBHeader for now. Part 3 00805 // of the book describes it in greater detail. 00806 00807 // Initialize the file size values here. 00808 PtrCommonFCBHeader->AllocationSize = AllocationSize; 00809 PtrCommonFCBHeader->FileSize = EndOfFile; 00810 00811 // The following will disable ValidDataLength support. However, your 00812 // FSD may choose to support this concept. 00813 PtrCommonFCBHeader->ValidDataLength.LowPart = 0xFFFFFFFF; 00814 PtrCommonFCBHeader->ValidDataLength.HighPart = 0x7FFFFFFF; 00815 00816 // Initialize other fields for the FCB here ... 00817 PtrFCB->PtrVCB = PtrVCB; 00818 00819 // caller MUST ensure that VCB has been acquired exclusively 00820 InsertTailList(&(PtrVCB->FCBListHead), &(PtrFCB->NextFCB)); 00821 00822 00823 InitializeListHead(&(PtrFCB->CCBListHead)); 00824 00825 // Initialize fields contained in the file object now. 00826 if( PtrFileObject ) 00827 { 00828 PtrFileObject->PrivateCacheMap = NULL; 00829 // Note that we could have just as well taken the value of PtrReqdFCB 00830 // directly below. The bottom line however is that the FsContext 00831 // field must point to a FSRTL_COMMON_FCB_HEADER structure. 00832 PtrFileObject->FsContext = (void *)(PtrCommonFCBHeader); 00833 PtrFileObject->SectionObjectPointer = &(PtrFCB->NTRequiredFCB.SectionObject) ; 00834 } 00835 00836 // Initialising the object name... 00837 PtrFCB->FCBName = PtrObjectName; 00838 00839 // Returning the FCB... 00840 *ReturnedFCB = PtrFCB; 00841 try_exit: NOTHING; 00842 } 00843 00844 finally 00845 { 00846 00847 } 00848 00849 return(RC); 00850 } 00851 00852 00853 /************************************************************************* 00854 * 00855 * Function: Ext2ReleaseFCB() 00856 * 00857 * Description: 00858 * Deallocate a previously allocated structure. 00859 * 00860 * Expected Interrupt Level (for execution) : 00861 * 00862 * IRQL_PASSIVE_LEVEL 00863 * 00864 * Return Value: None 00865 * 00866 *************************************************************************/ 00867 void NTAPI Ext2ReleaseFCB( 00868 PtrExt2FCB PtrFCB) 00869 { 00870 //KIRQL CurrentIrql; 00871 00872 AssertFCB( PtrFCB ); 00873 00874 if( PtrFCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_FCB ) 00875 { 00876 Ext2Panic( PtrFCB, PtrFCB->NodeIdentifier.NodeType, EXT2_NODE_TYPE_FCB ) ; 00877 } 00878 00879 00880 PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED; 00881 00882 /* 00883 // give back memory either to the zone or to the VMM 00884 if (!(PtrFCB->FCBFlags & EXT2_FCB_NOT_FROM_ZONE)) 00885 { 00886 // back to the zone 00887 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00888 ExFreeToZone(&(Ext2GlobalData.FCBZoneHeader), PtrFCB); 00889 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00890 } 00891 else 00892 { 00893 */ 00894 00895 ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.MainResource ); 00896 ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.PagingIoResource ); 00897 00898 RemoveEntryList(&(PtrFCB->NextFCB)); 00899 00900 if( PtrFCB->FCBName ) 00901 { 00902 Ext2ReleaseObjectName( PtrFCB->FCBName ); 00903 } 00904 00905 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrFCB); 00906 ExFreePool(PtrFCB); 00907 00908 /* 00909 } 00910 */ 00911 00912 return; 00913 } 00914 00915 /************************************************************************* 00916 * 00917 * Function: Ext2AllocateByteLocks() 00918 * 00919 * Description: 00920 * Allocate a new byte range lock structure and initialize it to NULL. 00921 * 00922 * Expected Interrupt Level (for execution) : 00923 * 00924 * IRQL_PASSIVE_LEVEL 00925 * 00926 * Return Value: A pointer to the Ext2ByteLocks structure OR NULL. 00927 * 00928 *************************************************************************/ 00929 PtrExt2FileLockInfo NTAPI Ext2AllocateByteLocks( 00930 void) 00931 { 00932 PtrExt2FileLockInfo PtrByteLocks = NULL; 00933 BOOLEAN AllocatedFromZone = TRUE; 00934 KIRQL CurrentIrql; 00935 00936 // first, try to allocate out of the zone 00937 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00938 if (!ExIsFullZone(&(Ext2GlobalData.ByteLockZoneHeader))) 00939 { 00940 // we have enough memory 00941 PtrByteLocks = (PtrExt2FileLockInfo)ExAllocateFromZone(&(Ext2GlobalData.ByteLockZoneHeader)); 00942 00943 // release the spinlock 00944 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00945 } 00946 else 00947 { 00948 // release the spinlock 00949 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 00950 00951 // if we failed to obtain from the zone, get it directly from the VMM 00952 PtrByteLocks = (PtrExt2FileLockInfo)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2FileLockInfo)) ); 00953 AllocatedFromZone = FALSE; 00954 } 00955 00956 // if we could not obtain the required memory, bug-check. 00957 // Do NOT do this in your commercial driver, instead handle the error gracefully ... 00958 if (!PtrByteLocks) 00959 { 00960 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2FileLockInfo)), 0); 00961 } 00962 00963 // zero out the allocated memory block 00964 RtlZeroMemory(PtrByteLocks, Ext2QuadAlign(sizeof(PtrExt2FileLockInfo))); 00965 00966 if (!AllocatedFromZone) 00967 { 00968 Ext2SetFlag(PtrByteLocks->FileLockFlags, EXT2_BYTE_LOCK_NOT_FROM_ZONE); 00969 } 00970 00971 return(PtrByteLocks); 00972 } 00973 00974 /************************************************************************* 00975 * 00976 * Function: Ext2ReleaseByteLocks() 00977 * 00978 * Description: 00979 * Deallocate a previously allocated structure. 00980 * 00981 * Expected Interrupt Level (for execution) : 00982 * 00983 * IRQL_PASSIVE_LEVEL 00984 * 00985 * Return Value: None 00986 * 00987 *************************************************************************/ 00988 void NTAPI Ext2ReleaseByteLocks( 00989 PtrExt2FileLockInfo PtrByteLocks) 00990 { 00991 KIRQL CurrentIrql; 00992 00993 ASSERT(PtrByteLocks); 00994 00995 // give back memory either to the zone or to the VMM 00996 if (!(PtrByteLocks->FileLockFlags & EXT2_BYTE_LOCK_NOT_FROM_ZONE)) { 00997 // back to the zone 00998 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 00999 ExFreeToZone(&(Ext2GlobalData.ByteLockZoneHeader), PtrByteLocks); 01000 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 01001 } 01002 else 01003 { 01004 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrByteLocks); 01005 ExFreePool(PtrByteLocks); 01006 } 01007 01008 return; 01009 } 01010 01011 01012 /************************************************************************* 01013 * 01014 * Function: Ext2AllocateIrpContext() 01015 * 01016 * Description: 01017 * The sample FSD creates an IRP context for each request received. This 01018 * routine simply allocates (and initializes to NULL) a Ext2IrpContext 01019 * structure. 01020 * Most of the fields in the context structure are then initialized here. 01021 * 01022 * Expected Interrupt Level (for execution) : 01023 * 01024 * IRQL_PASSIVE_LEVEL 01025 * 01026 * Return Value: A pointer to the IrpContext structure OR NULL. 01027 * 01028 *************************************************************************/ 01029 PtrExt2IrpContext NTAPI Ext2AllocateIrpContext( 01030 PIRP Irp, 01031 PDEVICE_OBJECT PtrTargetDeviceObject) 01032 { 01033 PtrExt2IrpContext PtrIrpContext = NULL; 01034 BOOLEAN AllocatedFromZone = TRUE; 01035 //KIRQL CurrentIrql; 01036 PIO_STACK_LOCATION PtrIoStackLocation = NULL; 01037 01038 /* 01039 // Allocation from zone not done at present... 01040 01041 // first, try to allocate out of the zone 01042 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 01043 if (!ExIsFullZone(&(Ext2GlobalData.IrpContextZoneHeader))) { 01044 // we have enough memory 01045 PtrIrpContext = (PtrExt2IrpContext)ExAllocateFromZone(&(Ext2GlobalData.IrpContextZoneHeader)); 01046 01047 // release the spinlock 01048 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 01049 } else { 01050 // release the spinlock 01051 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 01052 01053 01054 01055 01056 // if we failed to obtain from the zone, get it directly from the VMM 01057 PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) ); 01058 AllocatedFromZone = FALSE; 01059 } 01060 01061 //No Zone handling for now 01062 */ 01063 01064 PtrIrpContext = (PtrExt2IrpContext)Ext2AllocatePool(NonPagedPool, Ext2QuadAlign(sizeof(Ext2IrpContext)) ); 01065 AllocatedFromZone = FALSE; 01066 01067 // if we could not obtain the required memory, bug-check. 01068 // Do NOT do this in your commercial driver, instead handle the error gracefully ... 01069 if (!PtrIrpContext) 01070 { 01071 Ext2Panic(STATUS_INSUFFICIENT_RESOURCES, Ext2QuadAlign(sizeof(Ext2IrpContext)), 0); 01072 } 01073 01074 // zero out the allocated memory block 01075 RtlZeroMemory(PtrIrpContext, Ext2QuadAlign(sizeof(Ext2IrpContext))); 01076 01077 // set up some fields ... 01078 PtrIrpContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IRP_CONTEXT; 01079 PtrIrpContext->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2IrpContext)); 01080 01081 01082 PtrIrpContext->Irp = Irp; 01083 PtrIrpContext->TargetDeviceObject = PtrTargetDeviceObject; 01084 01085 // copy over some fields from the IRP and set appropriate flag values 01086 if (Irp) 01087 { 01088 PtrIoStackLocation = IoGetCurrentIrpStackLocation(Irp); 01089 ASSERT(PtrIoStackLocation); 01090 01091 PtrIrpContext->MajorFunction = PtrIoStackLocation->MajorFunction; 01092 PtrIrpContext->MinorFunction = PtrIoStackLocation->MinorFunction; 01093 01094 // Often, a FSD cannot honor a request for asynchronous processing 01095 // of certain critical requests. For example, a "close" request on 01096 // a file object can typically never be deferred. Therefore, do not 01097 // be surprised if sometimes your FSD (just like all other FSD 01098 // implementations on the Windows NT system) has to override the flag 01099 // below. 01100 if( PtrIoStackLocation->FileObject ) 01101 { 01102 if (IoIsOperationSynchronous(Irp) ) 01103 { 01104 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK); 01105 } 01106 } 01107 else 01108 { 01109 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK); 01110 } 01111 } 01112 01113 if (!AllocatedFromZone) 01114 { 01115 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_NOT_FROM_ZONE); 01116 } 01117 01118 // Are we top-level ? This information is used by the dispatching code 01119 // later (and also by the FSD dispatch routine) 01120 if (IoGetTopLevelIrp() != Irp) 01121 { 01122 // We are not top-level. Note this fact in the context structure 01123 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_NOT_TOP_LEVEL); 01124 } 01125 01126 InitializeListHead( &PtrIrpContext->SavedBCBsListHead ); 01127 01128 return(PtrIrpContext); 01129 } 01130 01131 01132 /************************************************************************* 01133 * 01134 * Function: Ext2ReleaseIrpContext() 01135 * 01136 * Description: 01137 * Deallocate a previously allocated structure. 01138 * 01139 * Expected Interrupt Level (for execution) : 01140 * 01141 * IRQL_PASSIVE_LEVEL 01142 * 01143 * Return Value: None 01144 * 01145 *************************************************************************/ 01146 void NTAPI Ext2ReleaseIrpContext( 01147 PtrExt2IrpContext PtrIrpContext) 01148 { 01149 KIRQL CurrentIrql; 01150 01151 ASSERT(PtrIrpContext); 01152 01153 // Flush the saved BCBs... 01154 Ext2FlushSavedBCBs( PtrIrpContext ); 01155 01156 // give back memory either to the zone or to the VMM 01157 if (!(PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_NOT_FROM_ZONE)) 01158 { 01159 // back to the zone 01160 KeAcquireSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), &CurrentIrql); 01161 ExFreeToZone(&(Ext2GlobalData.IrpContextZoneHeader), PtrIrpContext); 01162 KeReleaseSpinLock(&(Ext2GlobalData.ZoneAllocationSpinLock), CurrentIrql); 01163 } 01164 else 01165 { 01166 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrIrpContext); 01167 ExFreePool(PtrIrpContext); 01168 } 01169 01170 return; 01171 } 01172 01173 /************************************************************************* 01174 * 01175 * Function: Ext2PostRequest() 01176 * 01177 * Description: 01178 * Queue up a request for deferred processing (in the context of a system 01179 * worker thread). The caller must have locked the user buffer (if required) 01180 * 01181 * Expected Interrupt Level (for execution) : 01182 * 01183 * IRQL_PASSIVE_LEVEL 01184 * 01185 * Return Value: STATUS_PENDING 01186 * 01187 *************************************************************************/ 01188 NTSTATUS NTAPI Ext2PostRequest( 01189 PtrExt2IrpContext PtrIrpContext, 01190 PIRP PtrIrp) 01191 { 01192 NTSTATUS RC = STATUS_PENDING; 01193 01194 DebugTrace(DEBUG_TRACE_ASYNC, " === Asynchronous request. Deferring processing", 0); 01195 01196 // mark the IRP pending 01197 IoMarkIrpPending(PtrIrp); 01198 01199 // queue up the request 01200 ExInterlockedInsertTailList( 01201 &Ext2GlobalData.ThreadQueue.ThreadQueueListHead, 01202 &PtrIrpContext->ThreadQueueListEntry, 01203 &Ext2GlobalData.ThreadQueue.SpinLock ); 01204 01205 KeSetEvent( &Ext2GlobalData.ThreadQueue.QueueEvent, 0, FALSE ); 01206 01207 01208 /***************** not using system worker threads ***************** 01209 ExInitializeWorkItem(&(PtrIrpContext->WorkQueueItem), Ext2CommonDispatch, PtrIrpContext); 01210 ExQueueWorkItem( &( PtrIrpContext->WorkQueueItem ), DelayedWorkQueue ); 01211 // CriticalWorkQueue 01212 *****************************************************************************/ 01213 01214 // return status pending 01215 return(RC); 01216 } 01217 01218 01219 /************************************************************************* 01220 * 01221 * Function: Ext2CommonDispatch() 01222 * 01223 * Description: 01224 * The common dispatch routine invoked in the context of a system worker 01225 * thread. All we do here is pretty much case off the major function 01226 * code and invoke the appropriate FSD dispatch routine for further 01227 * processing. 01228 * 01229 * Expected Interrupt Level (for execution) : 01230 * 01231 * IRQL PASSIVE_LEVEL 01232 * 01233 * Return Value: None 01234 * 01235 *************************************************************************/ 01236 void NTAPI Ext2CommonDispatch( 01237 void *Context ) // actually an IRPContext structure 01238 { 01239 NTSTATUS RC = STATUS_SUCCESS; 01240 PtrExt2IrpContext PtrIrpContext = NULL; 01241 PIRP PtrIrp = NULL; 01242 01243 // The context must be a pointer to an IrpContext structure 01244 PtrIrpContext = (PtrExt2IrpContext)Context; 01245 ASSERT(PtrIrpContext); 01246 01247 // Assert that the Context is legitimate 01248 if ((PtrIrpContext->NodeIdentifier.NodeType != EXT2_NODE_TYPE_IRP_CONTEXT) || (PtrIrpContext->NodeIdentifier.NodeSize != Ext2QuadAlign(sizeof(Ext2IrpContext)))) 01249 { 01250 // This does not look good 01251 Ext2Panic(EXT2_ERROR_INTERNAL_ERROR, PtrIrpContext->NodeIdentifier.NodeType, PtrIrpContext->NodeIdentifier.NodeSize); 01252 } 01253 01254 // Get a pointer to the IRP structure 01255 PtrIrp = PtrIrpContext->Irp; 01256 ASSERT(PtrIrp); 01257 01258 // Now, check if the FSD was top level when the IRP was originally invoked 01259 // and set the thread context (for the worker thread) appropriately 01260 if (PtrIrpContext->IrpContextFlags & EXT2_IRP_CONTEXT_NOT_TOP_LEVEL) 01261 { 01262 // The FSD is not top level for the original request 01263 // Set a constant value in TLS to reflect this fact 01264 IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP); 01265 } 01266 01267 // Since the FSD routine will now be invoked in the context of this worker 01268 // thread, we should inform the FSD that it is perfectly OK to block in 01269 // the context of this thread 01270 Ext2SetFlag(PtrIrpContext->IrpContextFlags, EXT2_IRP_CONTEXT_CAN_BLOCK); 01271 01272 FsRtlEnterFileSystem(); 01273 01274 try 01275 { 01276 01277 // Pre-processing has been completed; check the Major Function code value 01278 // either in the IrpContext (copied from the IRP), or directly from the 01279 // IRP itself (we will need a pointer to the stack location to do that), 01280 // Then, switch based on the value on the Major Function code 01281 switch (PtrIrpContext->MajorFunction) 01282 { 01283 case IRP_MJ_CREATE: 01284 // Invoke the common create routine 01285 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CREATE request asynchronously .", 0); 01286 (void)Ext2CommonCreate(PtrIrpContext, PtrIrp, FALSE); 01287 break; 01288 case IRP_MJ_READ: 01289 // Invoke the common read routine 01290 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_READ request asynchronously .", 0); 01291 (void)Ext2CommonRead(PtrIrpContext, PtrIrp, FALSE); 01292 break; 01293 case IRP_MJ_WRITE: 01294 // Invoke the common write routine 01295 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_WRITE request asynchronously .", 0); 01296 (void)Ext2CommonWrite(PtrIrpContext, PtrIrp ); 01297 break; 01298 01299 case IRP_MJ_CLEANUP: 01300 // Invoke the common read routine 01301 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CLEANUP request asynchronously .", 0); 01302 (void)Ext2CommonCleanup(PtrIrpContext, PtrIrp, FALSE); 01303 break; 01304 case IRP_MJ_CLOSE: 01305 // Invoke the common read routine 01306 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing IRP_MJ_CLOSE request asynchronously .", 0); 01307 (void)Ext2CommonClose ( PtrIrpContext, PtrIrp, FALSE ); 01308 break; 01309 01310 // Continue with the remaining possible dispatch routines below ... 01311 default: 01312 // This is the case where we have an invalid major function 01313 DebugTrace(DEBUG_TRACE_ASYNC, " === Serviceing asynchronous request. \nUnable to recoganise the IRP!!! How can this be!!!", 0); 01314 PtrIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 01315 PtrIrp->IoStatus.Information = 0; 01316 01317 Ext2BreakPoint(); 01318 01319 IoCompleteRequest(PtrIrp, IO_NO_INCREMENT); 01320 break; 01321 } 01322 } 01323 except (Ext2ExceptionFilter(PtrIrpContext, GetExceptionInformation())) 01324 { 01325 RC = Ext2ExceptionHandler(PtrIrpContext, PtrIrp); 01326 Ext2LogEvent(EXT2_ERROR_INTERNAL_ERROR, RC); 01327 } 01328 01329 // Enable preemption 01330 FsRtlExitFileSystem(); 01331 01332 // Ensure that the "top-level" field is cleared 01333 IoSetTopLevelIrp(NULL); 01334 01335 PsTerminateSystemThread( RC ); 01336 01337 01338 return; 01339 } 01340 01341 /************************************************************************* 01342 * 01343 * Function: Ext2InitializeVCB() 01344 * 01345 * Description: 01346 * Perform the initialization for a VCB structure. 01347 * 01348 * Expected Interrupt Level (for execution) : 01349 * 01350 * IRQL PASSIVE_LEVEL 01351 * 01352 * Return Value: None 01353 * 01354 *************************************************************************/ 01355 void NTAPI Ext2InitializeVCB( 01356 PDEVICE_OBJECT PtrVolumeDeviceObject, 01357 PDEVICE_OBJECT PtrTargetDeviceObject, 01358 PVPB PtrVPB, 01359 PLARGE_INTEGER AllocationSize ) 01360 { 01361 NTSTATUS RC = STATUS_SUCCESS; 01362 PtrExt2VCB PtrVCB = NULL; 01363 BOOLEAN VCBResourceInitialized = FALSE; 01364 01365 PtrVCB = (PtrExt2VCB)(PtrVolumeDeviceObject->DeviceExtension); 01366 01367 // Zero it out (typically this has already been done by the I/O 01368 // Manager but it does not hurt to do it again)! 01369 RtlZeroMemory(PtrVCB, sizeof(Ext2VCB)); 01370 01371 // Initialize the signature fields 01372 PtrVCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_VCB; 01373 PtrVCB->NodeIdentifier.NodeSize = sizeof(Ext2VCB); 01374 01375 // Initialize the ERESOURCE objects. 01376 RC = ExInitializeResourceLite(&(PtrVCB->VCBResource)); 01377 RC = ExInitializeResourceLite(&(PtrVCB->PagingIoResource)); 01378 01379 ASSERT(NT_SUCCESS(RC)); 01380 VCBResourceInitialized = TRUE; 01381 01382 PtrVCB->TargetDeviceObject = PtrTargetDeviceObject; 01383 01384 PtrVCB->VCBDeviceObject = PtrVolumeDeviceObject; 01385 01386 PtrVCB->PtrVPB = PtrVPB; 01387 01388 // Initialize the list anchor (head) for some lists in this VCB. 01389 InitializeListHead(&(PtrVCB->FCBListHead)); 01390 InitializeListHead(&(PtrVCB->NextNotifyIRP)); 01391 InitializeListHead(&(PtrVCB->VolumeOpenListHead)); 01392 InitializeListHead(&(PtrVCB->ClosableFCBs.ClosableFCBListHead)); 01393 PtrVCB->ClosableFCBs.Count = 0; 01394 01395 // Initialize the notify IRP list mutex 01396 KeInitializeMutex(&(PtrVCB->NotifyIRPMutex), 0); 01397 01398 // Set the initial file size values appropriately. Note that your FSD may 01399 // wish to guess at the initial amount of information you would like to 01400 // read from the disk until you have really determined that this a valid 01401 // logical volume (on disk) that you wish to mount. 01402 PtrVCB->CommonVCBHeader.AllocationSize.QuadPart = AllocationSize->QuadPart; 01403 01404 PtrVCB->CommonVCBHeader.FileSize.QuadPart = AllocationSize->QuadPart; 01405 // You typically do not want to bother with valid data length callbacks 01406 // from the Cache Manager for the file stream opened for volume metadata 01407 // information 01408 PtrVCB->CommonVCBHeader.ValidDataLength.LowPart = 0xFFFFFFFF; 01409 PtrVCB->CommonVCBHeader.ValidDataLength.HighPart = 0x7FFFFFFF; 01410 01411 PtrVCB->CommonVCBHeader.IsFastIoPossible = FastIoIsNotPossible; 01412 01413 PtrVCB->CommonVCBHeader.Resource = &(PtrVCB->VCBResource); 01414 PtrVCB->CommonVCBHeader.PagingIoResource = &(PtrVCB->PagingIoResource); 01415 01416 // Create a stream file object for this volume. 01417 PtrVCB->PtrStreamFileObject = IoCreateStreamFileObject(NULL, 01418 PtrVCB->PtrVPB->RealDevice); 01419 ASSERT(PtrVCB->PtrStreamFileObject); 01420 01421 // Initialize some important fields in the newly created file object. 01422 PtrVCB->PtrStreamFileObject->FsContext = (void *)(&PtrVCB->CommonVCBHeader); 01423 PtrVCB->PtrStreamFileObject->FsContext2 = NULL; 01424 PtrVCB->PtrStreamFileObject->SectionObjectPointer = &(PtrVCB->SectionObject); 01425 01426 PtrVCB->PtrStreamFileObject->Vpb = PtrVPB; 01427 PtrVCB->PtrStreamFileObject->ReadAccess = TRUE; 01428 PtrVCB->PtrStreamFileObject->WriteAccess = TRUE; 01429 01430 // Link this chap onto the global linked list of all VCB structures. 01431 DebugTrace(DEBUG_TRACE_MISC, "*** Attempting to acquire Global Resource Exclusively [FileInfo]", 0); 01432 ExAcquireResourceExclusiveLite(&(Ext2GlobalData.GlobalDataResource), TRUE); 01433 InsertTailList(&(Ext2GlobalData.NextVCB), &(PtrVCB->NextVCB)); 01434 DebugTrace(DEBUG_TRACE_MISC, "*** Global Resource Acquired [FileInfo]", 0); 01435 01436 01437 01438 // Initialize caching for the stream file object. 01439 CcInitializeCacheMap(PtrVCB->PtrStreamFileObject, (PCC_FILE_SIZES)(&(PtrVCB->CommonVCBHeader.AllocationSize)), 01440 TRUE, // We will use pinned access. 01441 &(Ext2GlobalData.CacheMgrCallBacks), PtrVCB ); 01442 01443 01444 Ext2ReleaseResource(&(Ext2GlobalData.GlobalDataResource)); 01445 DebugTrace(DEBUG_TRACE_MISC, "*** Global Resource Released[FileInfo]", 0); 01446 01447 // Mark the fact that this VCB structure is initialized. 01448 Ext2SetFlag(PtrVCB->VCBFlags, EXT2_VCB_FLAGS_VCB_INITIALIZED); 01449 PtrVCB->PtrGroupDescriptors = NULL; 01450 PtrVCB->NoOfGroups = 0; 01451 return; 01452 } 01453 01454 01455 01456 /************************************************************************* 01457 * 01458 * Function: Ext2CompleteRequest() 01459 * 01460 * Description: 01461 * This routine completes a Irp. 01462 * 01463 * Expected Interrupt Level (for execution) : 01464 * 01465 * ??? 01466 * 01467 * Arguments: 01468 * 01469 * Irp - Supplies the Irp being processed 01470 * 01471 * Status - Supplies the status to complete the Irp with 01472 * 01473 * Return Value: none 01474 * 01475 *************************************************************************/ 01476 void NTAPI Ext2CompleteRequest( 01477 IN PIRP Irp OPTIONAL, 01478 IN NTSTATUS Status 01479 ) 01480 { 01481 // 01482 // If we have an Irp then complete the irp. 01483 // 01484 01485 if (Irp != NULL) 01486 { 01487 01488 // 01489 // We got an error, so zero out the information field before 01490 // completing the request if this was an input operation. 01491 // Otherwise IopCompleteRequest will try to copy to the user's buffer. 01492 // 01493 01494 if ( NT_ERROR(Status) && 01495 FlagOn(Irp->Flags, IRP_INPUT_OPERATION) ) { 01496 01497 Irp->IoStatus.Information = 0; 01498 } 01499 01500 Irp->IoStatus.Status = Status; 01501 01502 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 01503 } 01504 return; 01505 } 01506 01507 01508 /************************************************************************* 01509 * 01510 * Function: Ext2CreateNewCCB() 01511 * 01512 * Description: 01513 * We want to create a new CCB. 01514 * 01515 * Expected Interrupt Level (for execution) : 01516 * 01517 * IRQL_PASSIVE_LEVEL 01518 * 01519 * Return Value: A pointer to the CCB structure OR NULL. 01520 * 01521 *************************************************************************/ 01522 NTSTATUS NTAPI Ext2CreateNewCCB( 01523 PtrExt2CCB *ReturnedCCB, 01524 PtrExt2FCB PtrFCB, 01525 PFILE_OBJECT PtrFileObject ) 01526 { 01527 PtrExt2CCB PtrCCB; 01528 NTSTATUS RC = STATUS_SUCCESS; 01529 01530 try 01531 { 01532 01533 PtrCCB = Ext2AllocateCCB(); 01534 if (!PtrFCB) 01535 { 01536 // Assume lack of memory. 01537 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 01538 } 01539 PtrCCB->PtrFCB = PtrFCB; 01540 01541 PtrCCB->PtrFileObject = PtrFileObject; 01542 PtrCCB->CurrentByteOffset.QuadPart = 0; 01543 01544 if( PtrFCB->ClosableFCBs.OnClosableFCBList ) 01545 { 01546 // This FCB was on the Closable List... 01547 // Taking it off the list... 01548 // 01549 RemoveEntryList( &PtrFCB->ClosableFCBs.ClosableFCBList ); 01550 PtrFCB->ClosableFCBs.OnClosableFCBList = FALSE; 01551 PtrFCB->PtrVCB->ClosableFCBs.Count --; 01552 } 01553 01554 InterlockedIncrement( &PtrFCB->ReferenceCount ); 01555 InterlockedIncrement( &PtrFCB->OpenHandleCount ); 01556 01557 InsertTailList( &( PtrFCB->CCBListHead ), &(PtrCCB->NextCCB)); 01558 01559 *ReturnedCCB = PtrCCB; 01560 try_exit: NOTHING; 01561 } 01562 finally 01563 { 01564 01565 } 01566 01567 return(RC); 01568 } 01569 01570 01571 /************************************************************************* 01572 * 01573 * Function: Ext2DenyAccess() 01574 * 01575 * Description: 01576 * We want to deny access to an IRP 01577 * 01578 * Expected Interrupt Level (for execution) : 01579 * 01580 * IRQL_PASSIVE_LEVEL 01581 * 01582 * Return Value: NTSTATUS - STATUS_ACCESS_DENIED (always) 01583 * 01584 *************************************************************************/ 01585 NTSTATUS NTAPI Ext2DenyAccess( IN PIRP Irp ) 01586 { 01587 ASSERT( Irp ); 01588 01589 // Just return Access Denied 01590 Irp->IoStatus.Information = 0; 01591 Irp->IoStatus.Status = STATUS_ACCESS_DENIED; 01592 IoCompleteRequest( Irp, IO_DISK_INCREMENT ); 01593 01594 DebugTrace(DEBUG_TRACE_MISC, "DENYING ACCESS (this will do for now!)...", 0); 01595 01596 return STATUS_ACCESS_DENIED; 01597 } 01598 01599 01600 01601 /************************************************************************* 01602 * 01603 * Function: Ext2GetFCB_CCB_VCB_FromFileObject() 01604 * 01605 * Description: 01606 * This routine retrieves the FCB, CCB and VCB from the File Object... 01607 * 01608 * Expected Interrupt Level (for execution) : 01609 * 01610 * ? 01611 * 01612 * Return Value: NTSTATUS - STATUS_SUCCESS(always) 01613 * 01614 *************************************************************************/ 01615 NTSTATUS NTAPI Ext2GetFCB_CCB_VCB_FromFileObject ( 01616 IN PFILE_OBJECT PtrFileObject, 01617 OUT PtrExt2FCB *PPtrFCB, 01618 OUT PtrExt2CCB *PPtrCCB, 01619 OUT PtrExt2VCB *PPtrVCB ) 01620 { 01621 (*PPtrCCB) = (PtrExt2CCB)(PtrFileObject->FsContext2); 01622 if( *PPtrCCB ) 01623 { 01624 ASSERT((*PPtrCCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_CCB); 01625 (*PPtrFCB) = (*PPtrCCB)->PtrFCB; 01626 01627 ASSERT((*PPtrFCB)); 01628 01629 if ((*PPtrFCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB) 01630 { 01631 (*PPtrVCB) = (PtrExt2VCB)(*PPtrFCB); 01632 AssertVCB( (*PPtrVCB) ); 01633 01634 // No FCB 01635 (*PPtrFCB) = NULL; 01636 //found a VCB 01637 } 01638 else 01639 { 01640 AssertFCB( (*PPtrFCB) ); 01641 (*PPtrVCB) = (*PPtrFCB)->PtrVCB; 01642 AssertVCB( (*PPtrVCB) ); 01643 01644 } 01645 } 01646 else 01647 { 01648 // PtrFileObject->FsContext points to NTRequiredFCB 01649 (*PPtrFCB) = CONTAINING_RECORD( PtrFileObject->FsContext, Ext2FCB, NTRequiredFCB ); 01650 ASSERT((*PPtrFCB)); 01651 //(*PPtrFCB) = PtrFileObject->FsContext; 01652 01653 if ((*PPtrFCB)->NodeIdentifier.NodeType == EXT2_NODE_TYPE_FCB) 01654 { 01655 // Making sure I got it right... 01656 AssertFCB( *PPtrFCB ); 01657 (*PPtrVCB) = (*PPtrFCB)->PtrVCB; 01658 AssertVCB( *PPtrVCB ); 01659 } 01660 else 01661 { 01662 // This should be a VCB 01663 01664 (*PPtrVCB) = CONTAINING_RECORD( PtrFileObject->FsContext, Ext2VCB, CommonVCBHeader ); 01665 AssertVCB( *PPtrVCB ); 01666 01667 // No FCB 01668 (*PPtrFCB) = NULL; 01669 //found a VCB 01670 } 01671 01672 } 01673 return STATUS_SUCCESS; 01674 } 01675 01676 01677 void NTAPI Ext2CopyUnicodeString( PUNICODE_STRING PtrDestinationString, PUNICODE_STRING PtrSourceString ) 01678 { 01679 int Count; 01680 // Allcating space for Destination... 01681 PtrDestinationString->Length = PtrSourceString->Length; 01682 PtrDestinationString->MaximumLength = Ext2QuadAlign( PtrSourceString->Length + 2 ); 01683 PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength ); 01684 01685 // RtlCopyUnicodeString( PtrDestinationString, PtrSourceString ); 01686 01687 for( Count = 0 ; Count < (PtrSourceString->Length/2) ; Count++ ) 01688 { 01689 PtrDestinationString->Buffer[Count] = PtrSourceString->Buffer[Count]; 01690 } 01691 PtrDestinationString->Buffer[Count] = 0; 01692 01693 } 01694 01695 void NTAPI Ext2CopyWideCharToUnicodeString( 01696 PUNICODE_STRING PtrDestinationString, 01697 PCWSTR PtrSourceString ) 01698 { 01699 01700 int Count; 01701 01702 // Determining length... 01703 for( Count = 0 ; PtrSourceString[Count] != 0 ; Count++ ); 01704 01705 // Allcating space for Destination... 01706 PtrDestinationString->Length = Count * 2; 01707 PtrDestinationString->MaximumLength = Ext2QuadAlign( Count * 2 + 2 ); 01708 PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength ); 01709 01710 // Copying the string over... 01711 for( Count = 0 ; ; Count++ ) 01712 { 01713 PtrDestinationString->Buffer[Count] = PtrSourceString[Count]; 01714 if( PtrSourceString[Count] == 0 ) 01715 break; 01716 } 01717 } 01718 01719 01720 void NTAPI Ext2CopyCharToUnicodeString( 01721 PUNICODE_STRING PtrDestinationString, 01722 PCSTR PtrSourceString, 01723 USHORT SourceStringLength ) 01724 { 01725 int Count; 01726 // Allcating space for Destination... 01727 PtrDestinationString->Length = SourceStringLength * 2; 01728 PtrDestinationString->MaximumLength = Ext2QuadAlign( SourceStringLength * 2 + 2 ); 01729 PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength ); 01730 01731 // Copying the string over... 01732 for( Count = 0 ; Count < SourceStringLength ; Count++ ) 01733 { 01734 PtrDestinationString->Buffer[Count] = PtrSourceString[Count]; 01735 } 01736 PtrDestinationString->Buffer[Count] = 0; 01737 01738 } 01739 01740 void NTAPI Ext2CopyZCharToUnicodeString( PUNICODE_STRING PtrDestinationString, PCSTR PtrSourceString ) 01741 { 01742 01743 int Count; 01744 01745 // Determining length... 01746 for( Count = 0 ; PtrSourceString[Count] != 0 ; Count++ ); 01747 01748 // Allcating space for Destination... 01749 PtrDestinationString->Length = Count * 2; 01750 PtrDestinationString->MaximumLength = Ext2QuadAlign( Count * 2 + 2 ); 01751 PtrDestinationString->Buffer = Ext2AllocatePool( NonPagedPool, PtrDestinationString->MaximumLength ); 01752 01753 // Copying the string over... 01754 for( Count = 0 ; ; Count++ ) 01755 { 01756 PtrDestinationString->Buffer[Count] = PtrSourceString[Count]; 01757 if( PtrSourceString[Count] == 0 ) 01758 break; 01759 } 01760 } 01761 01762 void NTAPI Ext2ZerooutUnicodeString( PUNICODE_STRING PtrUnicodeString ) 01763 { 01764 PtrUnicodeString->Length = 0; 01765 PtrUnicodeString->MaximumLength =0; 01766 PtrUnicodeString->Buffer = 0; 01767 } 01768 01769 void NTAPI Ext2DeallocateUnicodeString( PUNICODE_STRING PtrUnicodeString ) 01770 { 01771 if( PtrUnicodeString && PtrUnicodeString->Buffer ) 01772 { 01773 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrUnicodeString->Buffer ); 01774 ExFreePool( PtrUnicodeString->Buffer ); 01775 } 01776 PtrUnicodeString->Length = 0; 01777 PtrUnicodeString->MaximumLength =0; 01778 PtrUnicodeString->Buffer = 0; 01779 } 01780 01781 PtrExt2FCB NTAPI Ext2GetUsedFCB( 01782 PtrExt2VCB PtrVCB ) 01783 { 01784 01785 BOOLEAN AllocatedFromZone = FALSE; 01786 PLIST_ENTRY PtrEntry = NULL; 01787 PtrExt2FCB PtrFCB = NULL; 01788 01789 ASSERT( PtrVCB ); 01790 if( PtrVCB->ClosableFCBs.Count < EXT2_MAXCLOSABLE_FCBS_LL ) 01791 { 01792 // 01793 // Too few Closable FCBs 01794 // Will not reuse any FCBs 01795 // Allocating a new one 01796 // 01797 return Ext2AllocateFCB(); 01798 } 01799 // 01800 // Obtaining a used FCB... 01801 // 01802 01803 // Retrieving the first entry in the closable FCB list... 01804 01805 PtrEntry = RemoveHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead ); 01806 01807 PtrFCB = CONTAINING_RECORD( PtrEntry, Ext2FCB, ClosableFCBs.ClosableFCBList ); 01808 01809 // Remembering if the FCB was allocated from the Zone... 01810 AllocatedFromZone = Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE ); 01811 01812 // 01813 // Close this FCB 01814 // 01815 if( !Ext2CloseClosableFCB( PtrFCB ) ) 01816 { 01817 // Couldn't close the FCB!! 01818 // 01819 InsertHeadList( &PtrVCB->ClosableFCBs.ClosableFCBListHead, 01820 &PtrFCB->ClosableFCBs.ClosableFCBList ); 01821 return Ext2AllocateFCB(); 01822 } 01823 01824 PtrVCB->ClosableFCBs.Count--; 01825 DebugTrace( DEBUG_TRACE_SPECIAL, "Count = %ld [Ext2GetUsedFCB]", PtrVCB->ClosableFCBs.Count ); 01826 01827 // 01828 // Getting the FCB ready for reuse by 01829 // zeroing it out... 01830 // 01831 RtlZeroMemory(PtrFCB, Ext2QuadAlign(sizeof(Ext2FCB))); 01832 01833 // set up some fields ... 01834 PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FCB; 01835 PtrFCB->NodeIdentifier.NodeSize = Ext2QuadAlign(sizeof(Ext2FCB)); 01836 01837 01838 if (!AllocatedFromZone) 01839 { 01840 Ext2SetFlag(PtrFCB->FCBFlags, EXT2_FCB_NOT_FROM_ZONE); 01841 } 01842 01843 return PtrFCB; 01844 } 01845 01846 BOOLEAN NTAPI Ext2CloseClosableFCB( 01847 PtrExt2FCB PtrFCB) 01848 { 01849 KIRQL Irql = 0; 01850 PFILE_OBJECT PtrFileObject = NULL; 01851 01852 AssertFCB( PtrFCB ); 01853 01854 // Attempting to acquire the FCB Exclusively... 01855 if(! ExAcquireResourceExclusiveLite( &(PtrFCB->NTRequiredFCB.MainResource ), FALSE ) ) 01856 { 01857 Ext2BreakPoint(); 01858 return FALSE; 01859 } 01860 01861 Irql = KeGetCurrentIrql( ); 01862 01863 if( PtrFCB->ReferenceCount ) 01864 { 01865 // How the hell can this happen!!! 01866 Ext2BreakPoint(); 01867 } 01868 if( PtrFCB->OpenHandleCount ) 01869 { 01870 // How the hell can this happen!!! 01871 Ext2BreakPoint(); 01872 } 01873 01874 // Deleting entry from VCB's FCB list... 01875 RemoveEntryList( &PtrFCB->NextFCB ); 01876 01877 PtrFCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_FREED; 01878 01879 PtrFileObject = PtrFCB->DcbFcb.Dcb.PtrDirFileObject; 01880 01881 if ( PtrFileObject ) 01882 { 01883 // 01884 // Clear the Cache Map... 01885 // 01886 if( PtrFileObject->PrivateCacheMap != NULL) 01887 { 01888 IO_STATUS_BLOCK Status; 01889 DebugTrace( DEBUG_TRACE_SPECIAL, ">>.........Flushing cache.........<<", 0 ); 01890 CcFlushCache( PtrFileObject->SectionObjectPointer, NULL, 0, &Status ); 01891 CcUninitializeCacheMap( PtrFileObject, NULL, NULL ); 01892 } 01893 // 01894 // The File Object is no longer required... 01895 // Close it by dereferenceing it!!! 01896 // 01897 PtrFileObject->FsContext = NULL; 01898 PtrFileObject->FsContext2 = NULL; 01899 ObDereferenceObject( PtrFileObject ); 01900 01901 PtrFCB->DcbFcb.Dcb.PtrDirFileObject = NULL; 01902 PtrFileObject = NULL; 01903 } 01904 01905 // Uninitialize the Resources... 01906 ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.MainResource ); 01907 ExDeleteResourceLite( &PtrFCB->NTRequiredFCB.PagingIoResource ); 01908 01909 // 01910 // Releasing the FCB Name Object... 01911 // 01912 if( PtrFCB->FCBName ) 01913 { 01914 DebugTrace( DEBUG_TRACE_SPECIAL, "Reusing FCB - File Name %S", PtrFCB->FCBName->ObjectName.Buffer ); 01915 Ext2ReleaseObjectName( PtrFCB->FCBName ); 01916 } 01917 else 01918 { 01919 DebugTrace( DEBUG_TRACE_SPECIAL, "Reusing FCB - File Name *Unknown*", 0 ); 01920 } 01921 return TRUE; 01922 } 01923 01924 01925 BOOLEAN NTAPI Ext2SaveBCB( 01926 PtrExt2IrpContext PtrIrpContext, 01927 PBCB PtrBCB, 01928 PFILE_OBJECT PtrFileObject) 01929 { 01930 PEXT2_SAVED_BCBS PtrSavedBCB; 01931 PLIST_ENTRY PtrEntry = NULL; 01932 01933 if( !PtrIrpContext ) 01934 { 01935 // 01936 // NULL passed instead of the IRP Context 01937 // This call should be ignored... 01938 // 01939 return TRUE; 01940 } 01941 01942 if( !AssertBCB( PtrBCB ) ) 01943 { 01944 DebugTrace( DEBUG_TRACE_MISC, "Not saving BCB!!! [Ext2SaveBCB]", 0 ); 01945 return FALSE; 01946 } 01947 01948 01949 DebugTrace( DEBUG_TRACE_SPECIAL, "Saving BCB [Ext2SaveBCB]", 0 ); 01950 01951 // Has the BCB been saved already? 01952 for( PtrEntry = PtrIrpContext->SavedBCBsListHead.Flink; 01953 PtrEntry != &PtrIrpContext->SavedBCBsListHead; 01954 PtrEntry = PtrEntry->Flink ) 01955 { 01956 PtrSavedBCB = CONTAINING_RECORD( PtrEntry, EXT2_SAVED_BCBS, SavedBCBsListEntry ); 01957 ASSERT( PtrSavedBCB ); 01958 if( PtrSavedBCB->PtrBCB == PtrBCB ) 01959 { 01960 01961 // A BCB for this file has already been saved for flushing... 01962 // Won't resave this one... 01963 return TRUE; 01964 } 01965 } 01966 01967 01968 // Reference the BCB 01969 CcRepinBcb( PtrBCB ); 01970 01971 // Now allocate a EXT2_SAVED_BCBS 01972 PtrSavedBCB = Ext2AllocatePool( NonPagedPool, 01973 Ext2QuadAlign( sizeof( EXT2_SAVED_BCBS ) ) ); 01974 if( !PtrSavedBCB ) 01975 return FALSE; 01976 PtrSavedBCB->NodeIdentifier.NodeSize = sizeof( EXT2_SAVED_BCBS ); 01977 PtrSavedBCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_SAVED_BCB; 01978 01979 PtrSavedBCB->PtrBCB = PtrBCB; 01980 // PtrSavedBCB->PtrFileObject = PtrFileObject; 01981 01982 // Now save it in the IRP Context 01983 InsertHeadList( &PtrIrpContext->SavedBCBsListHead, &PtrSavedBCB->SavedBCBsListEntry ); 01984 01985 PtrIrpContext->SavedCount++; 01986 // Return success... 01987 return TRUE; 01988 01989 } 01990 01991 01992 BOOLEAN NTAPI Ext2FlushSavedBCBs( 01993 PtrExt2IrpContext PtrIrpContext ) 01994 { 01995 01996 PLIST_ENTRY PtrEntry = NULL; 01997 PEXT2_SAVED_BCBS PtrSavedBCB = NULL; 01998 IO_STATUS_BLOCK Status; 01999 BOOLEAN RC = TRUE; 02000 02001 if( !IsListEmpty( &PtrIrpContext->SavedBCBsListHead ) ) 02002 { 02003 DebugTrace( DEBUG_TRACE_SPECIAL, "Flushing cache... - Ext2FlushSavedBCBs", 0 ); 02004 } 02005 while( !IsListEmpty( &PtrIrpContext->SavedBCBsListHead ) ) 02006 { 02007 02008 PtrEntry = RemoveTailList( &PtrIrpContext->SavedBCBsListHead ); 02009 if( !PtrEntry ) 02010 { 02011 // No more entries left... 02012 break; 02013 } 02014 02015 // Get the Saved BCB 02016 PtrSavedBCB = CONTAINING_RECORD( PtrEntry, EXT2_SAVED_BCBS, SavedBCBsListEntry ); 02017 if( PtrSavedBCB->NodeIdentifier.NodeType != EXT2_NODE_TYPE_SAVED_BCB ) 02018 { 02019 // Something is wrong... 02020 Ext2BreakPoint(); 02021 return FALSE; 02022 } 02023 02024 if( !AssertBCB( PtrSavedBCB->PtrBCB ) ) 02025 { 02026 // This BCB shouldn't have been saved in the first place... 02027 DebugTrace( DEBUG_TRACE_ERROR, "Unable to flush BCB - Skipping!!! [Ext2SaveBCB]", 0 ); 02028 continue; 02029 } 02030 02031 // Unpin and Flush the cache... 02032 CcUnpinRepinnedBcb( PtrSavedBCB->PtrBCB, TRUE, &Status ); 02033 02034 if( !NT_SUCCESS( Status.Status ) ) 02035 { 02036 // Failure in flushing... 02037 DebugTrace( DEBUG_TRACE_SPECIAL, "Failure flushing cache - Ext2FlushSavedBCBs", 0 ); 02038 RC = FALSE; 02039 } 02040 02041 // Release the Saved BCB 02042 PtrSavedBCB->NodeIdentifier.NodeType = EXT2_NODE_TYPE_INVALID; 02043 02044 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [misc]", PtrSavedBCB ); 02045 ExFreePool( PtrSavedBCB ); 02046 PtrSavedBCB = NULL; 02047 PtrIrpContext->SavedCount--; 02048 } 02049 02050 return RC; 02051 } 02052 02053 BOOLEAN NTAPI AssertBCB( PBCB PtrBCB ) 02054 { 02055 PFILE_OBJECT PtrFileObject = NULL; 02056 02057 /* 02058 * This routine is simplified version of the original 02059 * AssertBCB and doesn't make any assumptions about 02060 * the layout of undocumented BCB structure. 02061 * -- Filip Navara, 18/08/2004 02062 */ 02063 02064 PtrFileObject = CcGetFileObjectFromBcb ( PtrBCB ); 02065 if( !PtrFileObject ) 02066 { 02067 Ext2BreakPoint(); 02068 return FALSE; 02069 } 02070 else 02071 { 02072 return TRUE; 02073 } 02074 } 02075 02076 02077 ULONG NTAPI Ext2Align( ULONG NumberToBeAligned, ULONG Alignment ) 02078 { 02079 if( Alignment & ( Alignment - 1 ) ) 02080 { 02081 // 02082 // Alignment not a power of 2 02083 // Just returning 02084 // 02085 return NumberToBeAligned; 02086 } 02087 if( ( NumberToBeAligned & ( Alignment - 1 ) ) != 0 ) 02088 { 02089 NumberToBeAligned = NumberToBeAligned + Alignment; 02090 NumberToBeAligned = NumberToBeAligned & ( ~ (Alignment-1) ); 02091 } 02092 return NumberToBeAligned; 02093 } 02094 02095 LONGLONG NTAPI Ext2Align64( LONGLONG NumberToBeAligned, LONGLONG Alignment ) 02096 { 02097 if( Alignment & ( Alignment - 1 ) ) 02098 { 02099 // 02100 // Alignment not a power of 2 02101 // Just returning 02102 // 02103 return NumberToBeAligned; 02104 } 02105 if( ( NumberToBeAligned & ( Alignment - 1 ) ) != 0 ) 02106 { 02107 NumberToBeAligned = NumberToBeAligned + Alignment; 02108 NumberToBeAligned = NumberToBeAligned & ( ~ (Alignment-1) ); 02109 } 02110 return NumberToBeAligned; 02111 } 02112 02113 02114 ULONG NTAPI Ext2GetCurrentTime() 02115 { 02116 LARGE_INTEGER CurrentTime; 02117 ULONG Time; 02118 KeQuerySystemTime( &CurrentTime ); 02119 Time = (ULONG) ( (CurrentTime.QuadPart - Ext2GlobalData.TimeDiff.QuadPart) / 10000000 ); 02120 return Time; 02121 } Generated on Sat May 26 2012 04:15:48 for ReactOS by
1.7.6.1
|