ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

misc.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.