[ros-dev] [ros-diffs] [reactos] 01/01: [FASTFAT_NEW] This is not permitted by WDK license. We should rather import from MS GitHub and backport to NT5.2.

Alex Ionescu ionucu at videotron.ca
Fri Nov 24 21:13:16 UTC 2017


XP did not have a WDK. Did you mean XP IFS?

Best regards,
Alex Ionescu

On Thu, Nov 23, 2017 at 4:04 AM, Pierre Schweitzer <pierre at reactos.org>
wrote:

> https://git.reactos.org/?p=reactos.git;a=commitdiff;h=
> a913501626e599fba9d702149896f36046832deb
>
> commit a913501626e599fba9d702149896f36046832deb
> Author: Pierre Schweitzer <pierre at reactos.org>
> AuthorDate: Thu Nov 23 15:04:05 2017 +0100
>
>     [FASTFAT_NEW] This is not permitted by WDK license.
>     We should rather import from MS GitHub and backport to NT5.2.
> ---
>  drivers/filesystems/fastfat_new/CMakeLists.txt |   44 -
>  drivers/filesystems/fastfat_new/acchksup.c     |  374 --
>  drivers/filesystems/fastfat_new/allocsup.c     | 5001 ------------------
>  drivers/filesystems/fastfat_new/cachesup.c     | 1814 -------
>  drivers/filesystems/fastfat_new/cleanup.c      | 1027 ----
>  drivers/filesystems/fastfat_new/close.c        | 1224 -----
>  drivers/filesystems/fastfat_new/create.c       | 5684
> --------------------
>  drivers/filesystems/fastfat_new/devctrl.c      |  308 --
>  drivers/filesystems/fastfat_new/deviosup.c     | 3284 ------------
>  drivers/filesystems/fastfat_new/dirctrl.c      | 1526 ------
>  drivers/filesystems/fastfat_new/dirsup.c       | 3647 -------------
>  drivers/filesystems/fastfat_new/dumpsup.c      |  381 --
>  drivers/filesystems/fastfat_new/ea.c           | 2013 -------
>  drivers/filesystems/fastfat_new/easup.c        | 3811 --------------
>  drivers/filesystems/fastfat_new/fastfat.rc     |    5 -
>  drivers/filesystems/fastfat_new/fat.h          |  729 ---
>  drivers/filesystems/fastfat_new/fatdata.c      | 1424 -----
>  drivers/filesystems/fastfat_new/fatdata.h      |  328 --
>  drivers/filesystems/fastfat_new/fatinit.c      |  675 ---
>  drivers/filesystems/fastfat_new/fatprocs.h     | 2817 ----------
>  drivers/filesystems/fastfat_new/fatprocssrc.c  |    1 -
>  drivers/filesystems/fastfat_new/fatstruc.h     | 1614 ------
>  drivers/filesystems/fastfat_new/fileinfo.c     | 4635 ----------------
>  drivers/filesystems/fastfat_new/filobsup.c     |  547 --
>  drivers/filesystems/fastfat_new/flush.c        | 1261 -----
>  drivers/filesystems/fastfat_new/fsctrl.c       | 6726
> ------------------------
>  drivers/filesystems/fastfat_new/fspdisp.c      |  472 --
>  drivers/filesystems/fastfat_new/lfn.h          |   56 -
>  drivers/filesystems/fastfat_new/lockctrl.c     |  726 ---
>  drivers/filesystems/fastfat_new/namesup.c      | 1021 ----
>  drivers/filesystems/fastfat_new/nodetype.h     |  193 -
>  drivers/filesystems/fastfat_new/pnp.c          |  815 ---
>  drivers/filesystems/fastfat_new/read.c         | 1649 ------
>  drivers/filesystems/fastfat_new/resrcsup.c     |  807 ---
>  drivers/filesystems/fastfat_new/shutdown.c     |  304 --
>  drivers/filesystems/fastfat_new/sources        |   45 -
>  drivers/filesystems/fastfat_new/splaysup.c     |  504 --
>  drivers/filesystems/fastfat_new/strucsup.c     | 3626 -------------
>  drivers/filesystems/fastfat_new/timesup.c      |  364 --
>  drivers/filesystems/fastfat_new/verfysup.c     | 1853 -------
>  drivers/filesystems/fastfat_new/volinfo.c      | 1272 -----
>  drivers/filesystems/fastfat_new/workque.c      |  362 --
>  drivers/filesystems/fastfat_new/write.c        | 2830 ----------
>  43 files changed, 67799 deletions(-)
>
> diff --git a/drivers/filesystems/fastfat_new/CMakeLists.txt
> b/drivers/filesystems/fastfat_new/CMakeLists.txt
> deleted file mode 100644
> index f21d829e63..0000000000
> --- a/drivers/filesystems/fastfat_new/CMakeLists.txt
> +++ /dev/null
> @@ -1,44 +0,0 @@
> -
> -list(APPEND SOURCE
> -    acchksup.c
> -    allocsup.c
> -    cachesup.c
> -    cleanup.c
> -    close.c
> -    create.c
> -    devctrl.c
> -    deviosup.c
> -    dirctrl.c
> -    dirsup.c
> -    dumpsup.c
> -    ea.c
> -    easup.c
> -    fatdata.c
> -    fatinit.c
> -    fatprocssrc.c
> -    fileinfo.c
> -    filobsup.c
> -    flush.c
> -    fsctrl.c
> -    fspdisp.c
> -    lockctrl.c
> -    namesup.c
> -    pnp.c
> -    read.c
> -    resrcsup.c
> -    shutdown.c
> -    splaysup.c
> -    strucsup.c
> -    timesup.c
> -    verfysup.c
> -    volinfo.c
> -    workque.c
> -    write.c
> -    fatprocs.h)
> -
> -add_library(fastfat SHARED ${SOURCE} fastfat.rc)
> -set_module_type(fastfat kernelmodedriver)
> -target_link_libraries(fastfat ${PSEH_LIB} memcmp)
> -add_importlibs(fastfat ntoskrnl hal)
> -add_pch(fastfat fatprocs.h SOURCE)
> -add_cd_file(TARGET fastfat DESTINATION reactos/system32/drivers NO_CAB
> FOR all)
> diff --git a/drivers/filesystems/fastfat_new/acchksup.c
> b/drivers/filesystems/fastfat_new/acchksup.c
> deleted file mode 100644
> index b0c78a81a4..0000000000
> --- a/drivers/filesystems/fastfat_new/acchksup.c
> +++ /dev/null
> @@ -1,374 +0,0 @@
> -/*++
> -
> -Copyright (c) 1989-2000 Microsoft Corporation
> -
> -Module Name:
> -
> -    AcChkSup.c
> -
> -Abstract:
> -
> -    This module implements the FAT access checking routine
> -
> -
> ---*/
> -
> -#include "fatprocs.h"
> -
> -//
> -//  Our debug trace level
> -//
> -
> -#define Dbg                              (DEBUG_TRACE_ACCHKSUP)
> -
> -NTSTATUS
> -FatCreateRestrictEveryoneToken(
> -    IN PACCESS_TOKEN Token,
> -    OUT PACCESS_TOKEN *RestrictedToken
> -    );
> -
> -#ifdef ALLOC_PRAGMA
> -#pragma alloc_text(PAGE, FatCheckFileAccess)
> -#pragma alloc_text(PAGE, FatCreateRestrictEveryoneToken)
> -#pragma alloc_text(PAGE, FatExplicitDeviceAccessGranted)
> -#endif
> -
> -
> -BOOLEAN
> -FatCheckFileAccess (
> -    PIRP_CONTEXT IrpContext,
> -    IN UCHAR DirentAttributes,
> -    IN PACCESS_MASK DesiredAccess
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine checks if a desired access is allowed to a file
> represented
> -    by the specified DirentAttriubutes.
> -
> -Arguments:
> -
> -    DirentAttributes - Supplies the Dirent attributes to check access for
> -
> -    DesiredAccess - Supplies the desired access mask that we are checking
> for
> -
> -Return Value:
> -
> -    BOOLEAN - TRUE if access is allowed and FALSE otherwise
> -
> ---*/
> -
> -{
> -    BOOLEAN Result;
> -
> -    DebugTrace(+1, Dbg, "FatCheckFileAccess\n", 0);
> -    DebugTrace( 0, Dbg, "DirentAttributes = %8lx\n", DirentAttributes);
> -    DebugTrace( 0, Dbg, "DesiredAccess    = %8lx\n", *DesiredAccess);
> -
> -    //
> -    //  This procedures is programmed like a string of filters each
> -    //  filter checks to see if some access is allowed,  if it is not
> allowed
> -    //  the filter return FALSE to the user without further checks
> otherwise
> -    //  it moves on to the next filter.  The filter check is to check for
> -    //  desired access flags that are not allowed for a particular dirent
> -    //
> -
> -    Result = TRUE;
> -
> -    _SEH2_TRY {
> -
> -        //
> -        //  Check for Volume ID or Device Dirents, these are not allowed
> user
> -        //  access at all
> -        //
> -
> -        if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_VOLUME_ID) ||
> -            FlagOn(DirentAttributes, FAT_DIRENT_ATTR_DEVICE)) {
> -
> -            DebugTrace(0, Dbg, "Cannot access volume id or device\n", 0);
> -
> -            try_return( Result = FALSE );
> -        }
> -
> -        //
> -        //  Check the desired access for the object - we only blackball
> that
> -        //  we do not understand.  The model of filesystems using ACLs is
> that
> -        //  they do not type the ACL to the object the ACL is on.
> Permissions
> -        //  are not checked for consistency vs. the object type -
> dir/file.
> -        //
> -
> -        if (FlagOn(*DesiredAccess, ~(DELETE |
> -                                     READ_CONTROL |
> -                                     WRITE_OWNER |
> -                                     WRITE_DAC |
> -                                     SYNCHRONIZE |
> -                                     ACCESS_SYSTEM_SECURITY |
> -                                     FILE_WRITE_DATA |
> -                                     FILE_READ_EA |
> -                                     FILE_WRITE_EA |
> -                                     FILE_READ_ATTRIBUTES |
> -                                     FILE_WRITE_ATTRIBUTES |
> -                                     FILE_LIST_DIRECTORY |
> -                                     FILE_TRAVERSE |
> -                                     FILE_DELETE_CHILD |
> -                                     FILE_APPEND_DATA))) {
> -
> -            DebugTrace(0, Dbg, "Cannot open object\n", 0);
> -
> -            try_return( Result = FALSE );
> -        }
> -
> -        //
> -        //  Check for a read-only Dirent
> -        //
> -
> -        if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
> -
> -            //
> -            //  Check the desired access for a read-only dirent, we
> blackball
> -            //  WRITE, FILE_APPEND_DATA, FILE_ADD_FILE,
> -            //  FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD
> -            //
> -
> -            if (FlagOn(*DesiredAccess, ~(DELETE |
> -                                         READ_CONTROL |
> -                                         WRITE_OWNER |
> -                                         WRITE_DAC |
> -                                         SYNCHRONIZE |
> -                                         ACCESS_SYSTEM_SECURITY |
> -                                         FILE_READ_DATA |
> -                                         FILE_READ_EA |
> -                                         FILE_WRITE_EA |
> -                                         FILE_READ_ATTRIBUTES |
> -                                         FILE_WRITE_ATTRIBUTES |
> -                                         FILE_EXECUTE |
> -                                         FILE_LIST_DIRECTORY |
> -                                         FILE_TRAVERSE))) {
> -
> -                DebugTrace(0, Dbg, "Cannot open readonly\n", 0);
> -
> -                try_return( Result = FALSE );
> -            }
> -        }
> -
> -    try_exit: NOTHING;
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatCheckFileAccess );
> -
> -        DebugTrace(-1, Dbg, "FatCheckFileAccess -> %08lx\n", Result);
> -    } _SEH2_END;
> -
> -    UNREFERENCED_PARAMETER( IrpContext );
> -
> -    return Result;
> -}
> -
> -
> -NTSTATUS
> -FatExplicitDeviceAccessGranted (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PDEVICE_OBJECT DeviceObject,
> -    IN PACCESS_STATE AccessState,
> -    IN KPROCESSOR_MODE ProcessorMode
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This function asks whether the SID described in the input access
> state has
> -    been granted any explicit access to the given device object.  It does
> this
> -    by acquiring a token stripped of its ability to acquire access via the
> -    Everyone SID and re-doing the access check.
> -
> -Arguments:
> -
> -    DeviceObject - the device whose ACL will be checked
> -
> -    AccessState - the access state describing the security context to be
> checked
> -
> -    ProcessorMode - the mode this check should occur against
> -
> -Return Value:
> -
> -    NTSTATUS - Indicating whether explicit access was granted.
> -
> ---*/
> -
> -{
> -    NTSTATUS Status;
> -#ifndef __REACTOS__
> -    BOOLEAN Result;
> -#endif
> -
> -    PACCESS_TOKEN OriginalAccessToken;
> -    PACCESS_TOKEN RestrictedAccessToken;
> -
> -    PACCESS_TOKEN *EffectiveToken;
> -
> -    PRIVILEGE_SET PrivilegeSet;
> -
> -    ACCESS_MASK GrantedAccess;
> -
> -    //
> -    //  If the access state indicates that specific access other
> -    //  than traverse was acquired, either Everyone does have such
> -    //  access or explicit access was granted.  In both cases, we're
> -    //  happy to let this proceed.
> -    //
> -
> -    if (AccessState->PreviouslyGrantedAccess & (SPECIFIC_RIGHTS_ALL ^
> -                                                FILE_TRAVERSE)) {
> -
> -        return STATUS_SUCCESS;
> -    }
> -
> -    //
> -    //  If the manage volume privilege is held, this also permits access.
> -    //
> -
> -    PrivilegeSet.PrivilegeCount = 1;
> -    PrivilegeSet.Control = PRIVILEGE_SET_ALL_NECESSARY;
> -    PrivilegeSet.Privilege[0].Luid = RtlConvertLongToLuid(
> SE_MANAGE_VOLUME_PRIVILEGE );
> -    PrivilegeSet.Privilege[0].Attributes = 0;
> -
> -    if (SePrivilegeCheck( &PrivilegeSet,
> -                          &AccessState->SubjectSecurityContext,
> -                          ProcessorMode )) {
> -
> -        return STATUS_SUCCESS;
> -    }
> -
> -    //
> -    //  Capture the subject context as a prelude to everything below.
> -    //
> -
> -    SeLockSubjectContext( &AccessState->SubjectSecurityContext );
> -
> -    //
> -    //  Convert the token in the subject context into one which does not
> -    //  acquire access through the Everyone SID.
> -    //
> -    //  The logic for deciding which token is effective comes from
> -    //  SeQuerySubjectContextToken; since there is no natural way
> -    //  of getting a pointer to it, do it by hand.
> -    //
> -
> -    if (ARGUMENT_PRESENT( AccessState->SubjectSecurityContext.ClientToken
> )) {
> -        EffectiveToken = &AccessState->SubjectSecurityContext.
> ClientToken;
> -    } else {
> -        EffectiveToken = &AccessState->SubjectSecurityContext.
> PrimaryToken;
> -    }
> -
> -    OriginalAccessToken = *EffectiveToken;
> -    Status = FatCreateRestrictEveryoneToken( OriginalAccessToken,
> &RestrictedAccessToken );
> -
> -    if (!NT_SUCCESS(Status)) {
> -
> -        SeReleaseSubjectContext( &AccessState->SubjectSecurityContext );
> -        return Status;
> -    }
> -
> -    //
> -    //  Now see if the resulting context has access to the device through
> -    //  its explicitly granted access.  We swap in our restricted token
> -    //  for this check as the effective client token.
> -    //
> -
> -    *EffectiveToken = RestrictedAccessToken;
> -
> -#ifndef __REACTOS__
> -    Result = SeAccessCheck( DeviceObject->SecurityDescriptor,
> -#else
> -    SeAccessCheck( DeviceObject->SecurityDescriptor,
> -#endif
> -                            &AccessState->SubjectSecurityContext,
> -                            FALSE,
> -                            AccessState->OriginalDesiredAccess,
> -                            0,
> -                            NULL,
> -                            IoGetFileObjectGenericMapping(),
> -                            ProcessorMode,
> -                            &GrantedAccess,
> -                            &Status );
> -
> -    *EffectiveToken = OriginalAccessToken;
> -
> -    //
> -    //  Cleanup and return.
> -    //
> -
> -    SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
> -    ObDereferenceObject( RestrictedAccessToken );
> -
> -    return Status;
> -}
> -
> -
> -NTSTATUS
> -FatCreateRestrictEveryoneToken (
> -    IN PACCESS_TOKEN Token,
> -    OUT PACCESS_TOKEN *RestrictedToken
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This function takes a token as the input and returns a new restricted
> token
> -    from which Everyone sid has been disabled.  The resulting token may
> be used
> -    to find out if access is available to a user-sid by explicit means.
> -
> -Arguments:
> -
> -    Token - Input token from which Everyone sid needs to be deactivated.
> -
> -    RestrictedToken - Receives the the new restricted token.
> -        This must be released using ObDereferenceObject(*
> RestrictedToken);
> -
> -Return Value:
> -
> -    NTSTATUS - Returned by SeFilterToken.
> -
> ---*/
> -
> -{
> -    //
> -    // Array of sids to disable.
> -    //
> -
> -    TOKEN_GROUPS SidsToDisable;
> -
> -    NTSTATUS Status = STATUS_SUCCESS;
> -
> -    //
> -    //  Restricted token will contain the original sids with one change:
> -    //  If Everyone sid is present in the token, it will be marked for
> DenyOnly.
> -    //
> -
> -    *RestrictedToken = NULL;
> -
> -    //
> -    //  Put Everyone sid in the array of sids to disable. This will mark
> it
> -    //  for SE_GROUP_USE_FOR_DENY_ONLY and it'll only be applicable for
> Deny aces.
> -    //
> -
> -    SidsToDisable.GroupCount = 1;
> -    SidsToDisable.Groups[0].Attributes = 0;
> -    SidsToDisable.Groups[0].Sid = SeExports->SeWorldSid;
> -
> -    Status = SeFilterToken(
> -                 Token,            // Token that needs to be restricted.
> -                 0,                // No flags
> -                 &SidsToDisable,   // Disable everyone sid
> -                 NULL,             // Do not create any restricted sids
> -                 NULL,             // Do not delete any privileges
> -                 RestrictedToken   // Restricted token
> -                 );
> -
> -    return Status;
> -}
> -
> diff --git a/drivers/filesystems/fastfat_new/allocsup.c
> b/drivers/filesystems/fastfat_new/allocsup.c
> deleted file mode 100644
> index 79a9e7865a..0000000000
> --- a/drivers/filesystems/fastfat_new/allocsup.c
> +++ /dev/null
> @@ -1,5001 +0,0 @@
> -/*++
> -
> -Copyright (c) 1990-2000 Microsoft Corporation
> -
> -Module Name:
> -
> -    AllocSup.c
> -
> -Abstract:
> -
> -    This module implements the Allocation support routines for Fat.
> -
> -
> ---*/
> -
> -#include "fatprocs.h"
> -
> -//
> -//  The Bug check file id for this module
> -//
> -
> -#define BugCheckFileId                   (FAT_BUG_CHECK_ALLOCSUP)
> -
> -//
> -//  Local debug trace level
> -//
> -
> -#define Dbg                              (DEBUG_TRACE_ALLOCSUP)
> -
> -#define FatMin(a, b)    ((a) < (b) ? (a) : (b))
> -
> -//
> -//  This strucure is used by FatLookupFatEntry to remember a pinned page
> -//  of fat.
> -//
> -
> -typedef struct _FAT_ENUMERATION_CONTEXT {
> -
> -    VBO VboOfPinnedPage;
> -    PBCB Bcb;
> -    PVOID PinnedPage;
> -
> -} FAT_ENUMERATION_CONTEXT, *PFAT_ENUMERATION_CONTEXT;
> -
> -//
> -//  Local support routine prototypes
> -//
> -
> -VOID
> -FatLookupFatEntry(
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG FatIndex,
> -    IN OUT PULONG FatEntry,
> -    IN OUT PFAT_ENUMERATION_CONTEXT Context
> -    );
> -
> -VOID
> -FatSetFatRun(
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG StartingFatIndex,
> -    IN ULONG ClusterCount,
> -    IN BOOLEAN ChainTogether
> -    );
> -
> -UCHAR
> -FatLogOf(
> -    IN ULONG Value
> -    );
> -
> -//
> -//  Note that the KdPrint below will ONLY fire when the assert does.
> Leave it
> -//  alone.
> -//
> -
> -#if DBG
> -#define ASSERT_CURRENT_WINDOW_GOOD(VCB) {
>                \
> -    ULONG FreeClusterBitMapClear;
>                \
> -    ASSERT( (VCB)->FreeClusterBitMap.Buffer != NULL );
>                 \
> -    FreeClusterBitMapClear = RtlNumberOfClearBits(&(VCB)->FreeClusterBitMap);
>          \
> -    if ((VCB)->CurrentWindow->ClustersFree != FreeClusterBitMapClear) {
>                \
> -        KdPrint(("FAT: ClustersFree %x h != FreeClusterBitMapClear %x
> h\n",             \
> -                 (VCB)->CurrentWindow->ClustersFree,
>                 \
> -                 FreeClusterBitMapClear));
>               \
> -    }
>                \
> -    ASSERT( (VCB)->CurrentWindow->ClustersFree == FreeClusterBitMapClear
> );             \
> -}
> -#else
> -#define ASSERT_CURRENT_WINDOW_GOOD(VCB)
> -#endif
> -
> -//
> -//  The following macros provide a convenient way of hiding the details
> -//  of bitmap allocation schemes.
> -//
> -
> -
> -//
> -//  VOID
> -//  FatLockFreeClusterBitMap (
> -//      IN PVCB Vcb
> -//      );
> -//
> -
> -#define FatLockFreeClusterBitMap(VCB) {                         \
> -    ASSERT(KeAreApcsDisabled());                                \
> -    ExAcquireFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
> -    ASSERT_CURRENT_WINDOW_GOOD(VCB)                             \
> -}
> -
> -//
> -//  VOID
> -//  FatUnlockFreeClusterBitMap (
> -//      IN PVCB Vcb
> -//      );
> -//
> -
> -#define FatUnlockFreeClusterBitMap(VCB) {                       \
> -    ASSERT_CURRENT_WINDOW_GOOD(VCB)                             \
> -    ASSERT(KeAreApcsDisabled());                                \
> -    ExReleaseFastMutexUnsafe( &(VCB)->FreeClusterBitMapMutex ); \
> -}
> -
> -//
> -//  BOOLEAN
> -//  FatIsClusterFree (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG FatIndex
> -//      );
> -//
> -
> -#define FatIsClusterFree(IRPCONTEXT,VCB,FAT_INDEX)
>       \
> -    (RtlCheckBit(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2) == 0)
> -
> -//
> -//  VOID
> -//  FatFreeClusters  (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG FatIndex,
> -//      IN ULONG ClusterCount
> -//      );
> -//
> -
> -#define FatFreeClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) {
>      \
> -    if ((CLUSTER_COUNT) == 1) {
>      \
> -        FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_AVAILABLE);
> \
> -    } else {
>     \
> -        FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),FALSE);
>  \
> -    }
>      \
> -}
> -
> -//
> -//  VOID
> -//  FatAllocateClusters  (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG FatIndex,
> -//      IN ULONG ClusterCount
> -//      );
> -//
> -
> -#define FatAllocateClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) {
>   \
> -    if ((CLUSTER_COUNT) == 1) {
>   \
> -        FatSetFatEntry((IRPCONTEXT),(VCB),(FAT_INDEX),FAT_CLUSTER_LAST);
>  \
> -    } else {
>  \
> -        FatSetFatRun((IRPCONTEXT),(VCB),(FAT_INDEX),(CLUSTER_COUNT),TRUE);
> \
> -    }
>   \
> -}
> -
> -//
> -//  VOID
> -//  FatUnreserveClusters  (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG FatIndex,
> -//      IN ULONG ClusterCount
> -//      );
> -//
> -
> -#define FatUnreserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) {
>                     \
> -    ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap
> );   \
> -    ASSERT( (FAT_INDEX) >= 2);
>                   \
> -    RtlClearBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT));
>                 \
> -    if ((FAT_INDEX) < (VCB)->ClusterHint) {
>                    \
> -        (VCB)->ClusterHint = (FAT_INDEX);
>                    \
> -    }
>                    \
> -}
> -
> -//
> -//  VOID
> -//  FatReserveClusters  (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG FatIndex,
> -//      IN ULONG ClusterCount
> -//      );
> -//
> -//  Handle wrapping the hint back to the front.
> -//
> -
> -#define FatReserveClusters(IRPCONTEXT,VCB,FAT_INDEX,CLUSTER_COUNT) {
>                     \
> -    ULONG _AfterRun = (FAT_INDEX) + (CLUSTER_COUNT);
>                   \
> -    ASSERT( (FAT_INDEX) + (CLUSTER_COUNT) - 2 <= (VCB)->FreeClusterBitMap.SizeOfBitMap
> );   \
> -    ASSERT( (FAT_INDEX) >= 2);
>                   \
> -    RtlSetBits(&(VCB)->FreeClusterBitMap,(FAT_INDEX)-2,(CLUSTER_COUNT));
>                   \
> -
>                   \
> -    if (_AfterRun - 2 >= (VCB)->FreeClusterBitMap.SizeOfBitMap) {
>                    \
> -        _AfterRun = 2;
>                   \
> -    }
>                    \
> -    if (RtlCheckBit(&(VCB)->FreeClusterBitMap, _AfterRun - 2))  {
>                            \
> -        (VCB)->ClusterHint = RtlFindClearBits( &(VCB)->FreeClusterBitMap,
> 1, _AfterRun - 2) + 2;    \
> -        if (1 == (VCB)->ClusterHint)  {
>                            \
> -            (VCB)->ClusterHint = 2;
>                    \
> -        }
>                    \
> -    }
>                    \
> -    else {
>                   \
> -        (VCB)->ClusterHint = _AfterRun;
>                    \
> -    }
>                    \
> -}
> -
> -//
> -//  ULONG
> -//  FatFindFreeClusterRun (
> -//      IN PIRP_CONTEXT IrpContext,
> -//      IN PVCB Vcb,
> -//      IN ULONG ClusterCount,
> -//      IN ULONG AlternateClusterHint
> -//      );
> -//
> -//  Do a special check if only one cluster is desired.
> -//
> -
> -#define FatFindFreeClusterRun(IRPCONTEXT,VCB,CLUSTER_COUNT,CLUSTER_HINT)
> ( \
> -    (CLUSTER_COUNT == 1) &&
>   \
> -    FatIsClusterFree((IRPCONTEXT), (VCB), (CLUSTER_HINT)) ?
>   \
> -        (CLUSTER_HINT) :
>  \
> -        RtlFindClearBits( &(VCB)->FreeClusterBitMap,
>  \
> -                          (CLUSTER_COUNT),
>  \
> -                          (CLUSTER_HINT) - 2) + 2
>   \
> -)
> -
> -//
> -//  FAT32: Define the maximum size of the FreeClusterBitMap to be the
> -//  maximum size of a FAT16 FAT.  If there are more clusters on the
> -//  volume than can be represented by this many bytes of bitmap, the
> -//  FAT will be split into "buckets", each of which does fit.
> -//
> -//  Note this count is in clusters/bits of bitmap.
> -//
> -
> -#define MAX_CLUSTER_BITMAP_SIZE         (1 << 16)
> -
> -//
> -//  Calculate the window a given cluster number is in.
> -//
> -
> -#define FatWindowOfCluster(C)           (((C) - 2) /
> MAX_CLUSTER_BITMAP_SIZE)
> -
> -#ifdef ALLOC_PRAGMA
> -#pragma alloc_text(PAGE, FatAddFileAllocation)
> -#pragma alloc_text(PAGE, FatAllocateDiskSpace)
> -#pragma alloc_text(PAGE, FatDeallocateDiskSpace)
> -#pragma alloc_text(PAGE, FatExamineFatEntries)
> -#pragma alloc_text(PAGE, FatInterpretClusterType)
> -#pragma alloc_text(PAGE, FatLogOf)
> -#pragma alloc_text(PAGE, FatLookupFatEntry)
> -#pragma alloc_text(PAGE, FatLookupFileAllocation)
> -#pragma alloc_text(PAGE, FatLookupFileAllocationSize)
> -#pragma alloc_text(PAGE, FatMergeAllocation)
> -#pragma alloc_text(PAGE, FatSetFatEntry)
> -#pragma alloc_text(PAGE, FatSetFatRun)
> -#pragma alloc_text(PAGE, FatSetupAllocationSupport)
> -#pragma alloc_text(PAGE, FatSplitAllocation)
> -#pragma alloc_text(PAGE, FatTearDownAllocationSupport)
> -#pragma alloc_text(PAGE, FatTruncateFileAllocation)
> -#endif
> -
> -
> -INLINE
> -ULONG
> -FatSelectBestWindow(
> -    IN PVCB Vcb
> -    )
> -/*++
> -
> -Routine Description:
> -
> -    Choose a window to allocate clusters from.   Order of preference is:
> -
> -    1.  First window with >50% free clusters
> -    2.  First empty window
> -    3.  Window with greatest number of free clusters.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb for the volume
> -
> -Return Value:
> -
> -    'Best window' number (index into Vcb->Windows[])
> -
> ---*/
> -{
> -    ULONG i, Fave = 0;
> -    ULONG MaxFree = 0;
> -    ULONG FirstEmpty = -1;
> -    ULONG ClustersPerWindow = MAX_CLUSTER_BITMAP_SIZE;
> -
> -    ASSERT( 1 != Vcb->NumberOfWindows);
> -
> -    for (i = 0; i < Vcb->NumberOfWindows; i++) {
> -
> -        if (Vcb->Windows[i].ClustersFree == ClustersPerWindow)  {
> -
> -            if (-1 == FirstEmpty)  {
> -
> -                //
> -                //  Keep note of the first empty window on the disc
> -                //
> -
> -                FirstEmpty = i;
> -            }
> -        }
> -        else if (Vcb->Windows[i].ClustersFree > MaxFree)  {
> -
> -            //
> -            //  This window has the most free clusters,  so far
> -            //
> -
> -            MaxFree = Vcb->Windows[i].ClustersFree;
> -            Fave = i;
> -
> -            //
> -            //  If this window has >50% free clusters,  then we will take
> it,
> -            //  so don't bother considering more windows.
> -            //
> -
> -            if (MaxFree >= (ClustersPerWindow >> 1))  {
> -
> -                break;
> -            }
> -        }
> -    }
> -
> -    //
> -    //  If there were no windows with 50% or more freespace,  then select
> the
> -    //  first empty window on the disc,  if any - otherwise we'll just go
> with
> -    //  the one with the most free clusters.
> -    //
> -
> -    if ((MaxFree < (ClustersPerWindow >> 1)) && (-1 != FirstEmpty))  {
> -
> -        Fave = FirstEmpty;
> -    }
> -
> -    return Fave;
> -}
> -
> -
> -VOID
> -FatSetupAllocationSupport (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine fills in the Allocation Support structure in the Vcb.
> -    Most entries are computed using fat.h macros supplied with data from
> -    the Bios Parameter Block.  The free cluster count, however, requires
> -    going to the Fat and actually counting free sectors.  At the same time
> -    the free cluster bit map is initalized.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to fill in.
> -
> ---*/
> -
> -{
> -#ifndef __REACTOS__
> -    ULONG BitMapSize;
> -    PVOID BitMapBuffer;
> -#endif
> -    ULONG BitIndex;
> -
> -#ifndef __REACTOS__
> -    PBCB Bcb;
> -
> -    ULONG Page;
> -    ULONG Offset;
> -    ULONG FatIndexBitSize;
> -#endif
> -    ULONG ClustersDescribableByFat;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatSetupAllocationSupport\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb = %8lx\n", Vcb);
> -
> -    //
> -    //  Compute a number of fields for Vcb.AllocationSupport
> -    //
> -
> -    Vcb->AllocationSupport.RootDirectoryLbo = FatRootDirectoryLbo(
> &Vcb->Bpb );
> -    Vcb->AllocationSupport.RootDirectorySize = FatRootDirectorySize(
> &Vcb->Bpb );
> -
> -    Vcb->AllocationSupport.FileAreaLbo = FatFileAreaLbo( &Vcb->Bpb );
> -
> -    Vcb->AllocationSupport.NumberOfClusters = FatNumberOfClusters(
> &Vcb->Bpb );
> -
> -    Vcb->AllocationSupport.FatIndexBitSize = FatIndexBitSize( &Vcb->Bpb
> );
> -
> -    Vcb->AllocationSupport.LogOfBytesPerSector = FatLogOf(Vcb->Bpb.
> BytesPerSector);
> -    Vcb->AllocationSupport.LogOfBytesPerCluster =
> FatLogOf(FatBytesPerCluster( &Vcb->Bpb ));
> -    Vcb->AllocationSupport.NumberOfFreeClusters = 0;
> -
> -    //
> -    //  Deal with a bug in DOS 5 format, if the Fat is not big enough to
> -    //  describe all the clusters on the disk, reduce this number.  We
> expect
> -    //  that fat32 volumes will not have this problem.
> -    //
> -    //  Turns out this was not a good assumption.  We have to do this
> always now.
> -    //
> -
> -    ClustersDescribableByFat = ( ((FatIsFat32(Vcb)?
> Vcb->Bpb.LargeSectorsPerFat :
> -
> Vcb->Bpb.SectorsPerFat) *
> -                                  Vcb->Bpb.BytesPerSector * 8)
> -                                 / FatIndexBitSize(&Vcb->Bpb) ) - 2;
> -
> -    if (Vcb->AllocationSupport.NumberOfClusters >
> ClustersDescribableByFat) {
> -
> -        Vcb->AllocationSupport.NumberOfClusters =
> ClustersDescribableByFat;
> -    }
> -
> -    //
> -    //  Extend the virtual volume file to include the Fat
> -    //
> -
> -    {
> -        CC_FILE_SIZES FileSizes;
> -
> -        FileSizes.AllocationSize.QuadPart =
> -        FileSizes.FileSize.QuadPart = (FatReservedBytes( &Vcb->Bpb ) +
> -                                       FatBytesPerFat( &Vcb->Bpb ));
> -        FileSizes.ValidDataLength = FatMaxLarge;
> -
> -        if ( Vcb->VirtualVolumeFile->PrivateCacheMap == NULL ) {
> -
> -            CcInitializeCacheMap( Vcb->VirtualVolumeFile,
> -                                  &FileSizes,
> -                                  TRUE,
> -                                  &FatData.CacheManagerNoOpCallbacks,
> -                                  Vcb );
> -
> -        } else {
> -
> -            CcSetFileSizes( Vcb->VirtualVolumeFile, &FileSizes );
> -        }
> -    }
> -
> -    _SEH2_TRY {
> -
> -        if (FatIsFat32(Vcb) &&
> -            Vcb->AllocationSupport.NumberOfClusters >
> MAX_CLUSTER_BITMAP_SIZE) {
> -
> -            Vcb->NumberOfWindows = (Vcb->AllocationSupport.NumberOfClusters
> +
> -                                    MAX_CLUSTER_BITMAP_SIZE - 1) /
> -                                   MAX_CLUSTER_BITMAP_SIZE;
> -
> -#ifndef __REACTOS__
> -            BitMapSize = MAX_CLUSTER_BITMAP_SIZE;
> -#endif
> -
> -        } else {
> -
> -            Vcb->NumberOfWindows = 1;
> -#ifndef __REACTOS__
> -            BitMapSize = Vcb->AllocationSupport.NumberOfClusters;
> -#endif
> -        }
> -
> -        Vcb->Windows = FsRtlAllocatePoolWithTag( PagedPool,
> -                                                 Vcb->NumberOfWindows *
> sizeof(FAT_WINDOW),
> -                                                 TAG_FAT_WINDOW );
> -
> -        RtlInitializeBitMap( &Vcb->FreeClusterBitMap,
> -                             NULL,
> -                             0 );
> -
> -        //
> -        //  Chose a FAT window to begin operation in.
> -        //
> -
> -        if (Vcb->NumberOfWindows > 1) {
> -
> -            //
> -            //  Read the fat and count up free clusters.  We bias by the
> two reserved
> -            //  entries in the FAT.
> -            //
> -
> -            FatExamineFatEntries( IrpContext, Vcb,
> -                                  2,
> -                                  Vcb->AllocationSupport.NumberOfClusters
> + 2 - 1,
> -                                  TRUE,
> -                                  NULL,
> -                                  NULL);
> -
> -
> -            //
> -            //  Pick a window to begin allocating from
> -            //
> -
> -            Vcb->CurrentWindow = &Vcb->Windows[ FatSelectBestWindow(
> Vcb)];
> -
> -        } else {
> -
> -            Vcb->CurrentWindow = &Vcb->Windows[0];
> -
> -            //
> -            //  Carefully bias ourselves by the two reserved entries in
> the FAT.
> -            //
> -
> -            Vcb->CurrentWindow->FirstCluster = 2;
> -            Vcb->CurrentWindow->LastCluster = Vcb->AllocationSupport.NumberOfClusters
> + 2 - 1;
> -        }
> -
> -        //
> -        //  Now transition to the FAT window we have chosen.
> -        //
> -
> -        FatExamineFatEntries( IrpContext, Vcb,
> -                              0,
> -                              0,
> -                              FALSE,
> -                              Vcb->CurrentWindow,
> -                              NULL);
> -
> -        //
> -        //  Now set the ClusterHint to the first free bit in our favorite
> -        //  window (except the ClusterHint is off by two).
> -        //
> -
> -        Vcb->ClusterHint =
> -            (BitIndex = RtlFindClearBits( &Vcb->FreeClusterBitMap, 1, 0
> )) != -1 ?
> -                BitIndex + 2 : 2;
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatSetupAllocationSupport );
> -
> -        //
> -        //  If we hit an exception, back out.
> -        //
> -
> -        if (_SEH2_AbnormalTermination()) {
> -
> -            FatTearDownAllocationSupport( IrpContext, Vcb );
> -        }
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatTearDownAllocationSupport (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine prepares the volume for closing.  Specifically, we must
> -    release the free fat bit map buffer, and uninitialize the dirty fat
> -    Mcb.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to fill in.
> -
> -Return Value:
> -
> -    VOID
> -
> ---*/
> -
> -{
> -    DebugTrace(+1, Dbg, "FatTearDownAllocationSupport\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb = %8lx\n", Vcb);
> -
> -    PAGED_CODE();
> -
> -    //
> -    //  If there are FAT buckets, free them.
> -    //
> -
> -    if ( Vcb->Windows != NULL ) {
> -
> -        ExFreePool( Vcb->Windows );
> -        Vcb->Windows = NULL;
> -    }
> -
> -    //
> -    //  Free the memory associated with the free cluster bitmap.
> -    //
> -
> -    if ( Vcb->FreeClusterBitMap.Buffer != NULL ) {
> -
> -        ExFreePool( Vcb->FreeClusterBitMap.Buffer );
> -
> -        //
> -        //  NULL this field as an flag.
> -        //
> -
> -        Vcb->FreeClusterBitMap.Buffer = NULL;
> -    }
> -
> -    //
> -    //  And remove all the runs in the dirty fat Mcb
> -    //
> -
> -    FatRemoveMcbEntry( Vcb, &Vcb->DirtyFatMcb, 0, 0xFFFFFFFF );
> -
> -    DebugTrace(-1, Dbg, "FatTearDownAllocationSupport -> (VOID)\n", 0);
> -
> -    UNREFERENCED_PARAMETER( IrpContext );
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatLookupFileAllocation (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PFCB FcbOrDcb,
> -    IN VBO Vbo,
> -    OUT PLBO Lbo,
> -    OUT PULONG ByteCount,
> -    OUT PBOOLEAN Allocated,
> -    OUT PBOOLEAN EndOnMax,
> -    OUT PULONG Index
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine looks up the existing mapping of VBO to LBO for a
> -    file/directory.  The information it queries is either stored in the
> -    mcb field of the fcb/dcb or it is stored on in the fat table and
> -    needs to be retrieved and decoded, and updated in the mcb.
> -
> -Arguments:
> -
> -    FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being queried
> -
> -    Vbo - Supplies the VBO whose LBO we want returned
> -
> -    Lbo - Receives the LBO corresponding to the input Vbo if one exists
> -
> -    ByteCount - Receives the number of bytes within the run the run
> -                that correpond between the input vbo and output lbo.
> -
> -    Allocated - Receives TRUE if the Vbo does have a corresponding Lbo
> -                and FALSE otherwise.
> -
> -    EndOnMax - Receives TRUE if the run ends in the maximal FAT cluster,
> -                which results in a fractional bytecount.
> -
> -    Index - Receives the Index of the run
> -
> ---*/
> -
> -{
> -    VBO CurrentVbo;
> -    LBO CurrentLbo;
> -    LBO PriorLbo;
> -
> -    VBO FirstVboOfCurrentRun;
> -    LBO FirstLboOfCurrentRun;
> -
> -    BOOLEAN LastCluster;
> -    ULONG Runs;
> -
> -    PVCB Vcb;
> -    FAT_ENTRY FatEntry;
> -    ULONG BytesPerCluster;
> -    ULARGE_INTEGER BytesOnVolume;
> -
> -    FAT_ENUMERATION_CONTEXT Context;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatLookupFileAllocation\n", 0);
> -    DebugTrace( 0, Dbg, "  FcbOrDcb  = %8lx\n", FcbOrDcb);
> -    DebugTrace( 0, Dbg, "  Vbo       = %8lx\n", Vbo);
> -    DebugTrace( 0, Dbg, "  Lbo       = %8lx\n", Lbo);
> -    DebugTrace( 0, Dbg, "  ByteCount = %8lx\n", ByteCount);
> -    DebugTrace( 0, Dbg, "  Allocated = %8lx\n", Allocated);
> -
> -    Context.Bcb = NULL;
> -
> -    Vcb = FcbOrDcb->Vcb;
> -
> -    *EndOnMax = FALSE;
> -
> -    //
> -    //  Check the trivial case that the mapping is already in our
> -    //  Mcb.
> -    //
> -
> -    if ( FatLookupMcbEntry(Vcb, &FcbOrDcb->Mcb, Vbo, Lbo, ByteCount,
> Index) ) {
> -
> -        *Allocated = TRUE;
> -
> -        ASSERT( ByteCount != 0);
> -
> -        //
> -        //  Detect the overflow case, trim and claim the condition.
> -        //
> -
> -        if (Vbo + *ByteCount == 0) {
> -
> -            *EndOnMax = TRUE;
> -        }
> -
> -        DebugTrace( 0, Dbg, "Found run in Mcb.\n", 0);
> -        DebugTrace(-1, Dbg, "FatLookupFileAllocation -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    //
> -    //  Initialize the Vcb, the cluster size, LastCluster, and
> -    //  FirstLboOfCurrentRun (to be used as an indication of the first
> -    //  iteration through the following while loop).
> -    //
> -
> -    BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
> -
> -    BytesOnVolume.QuadPart = UInt32x32To64( Vcb->AllocationSupport.NumberOfClusters,
> BytesPerCluster );
> -
> -    LastCluster = FALSE;
> -    FirstLboOfCurrentRun = 0;
> -
> -    //
> -    //  Discard the case that the request extends beyond the end of
> -    //  allocation.  Note that if the allocation size if not known
> -    //  AllocationSize is set to 0xffffffff.
> -    //
> -
> -    if ( Vbo >= FcbOrDcb->Header.AllocationSize.LowPart ) {
> -
> -        *Allocated = FALSE;
> -
> -        DebugTrace( 0, Dbg, "Vbo beyond end of file.\n", 0);
> -        DebugTrace(-1, Dbg, "FatLookupFileAllocation -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    //
> -    //  The Vbo is beyond the last Mcb entry.  So we adjust Current
> Vbo/Lbo
> -    //  and FatEntry to describe the beginning of the last entry in the
> Mcb.
> -    //  This is used as initialization for the following loop.
> -    //
> -    //  If the Mcb was empty, we start at the beginning of the file with
> -    //  CurrentVbo set to 0 to indicate a new run.
> -    //
> -
> -    if (FatLookupLastMcbEntry( Vcb, &FcbOrDcb->Mcb, &CurrentVbo,
> &CurrentLbo, &Runs )) {
> -
> -        DebugTrace( 0, Dbg, "Current Mcb size = %8lx.\n", CurrentVbo + 1);
> -
> -        CurrentVbo -= (BytesPerCluster - 1);
> -        CurrentLbo -= (BytesPerCluster - 1);
> -
> -        //
> -        //  Convert an index to a count.
> -        //
> -
> -        Runs += 1;
> -
> -    } else {
> -
> -        DebugTrace( 0, Dbg, "Mcb empty.\n", 0);
> -
> -        //
> -        //  Check for an FcbOrDcb that has no allocation
> -        //
> -
> -        if (FcbOrDcb->FirstClusterOfFile == 0) {
> -
> -            *Allocated = FALSE;
> -
> -            DebugTrace( 0, Dbg, "File has no allocation.\n", 0);
> -            DebugTrace(-1, Dbg, "FatLookupFileAllocation -> (VOID)\n", 0);
> -            return;
> -
> -        } else {
> -
> -            CurrentVbo = 0;
> -            CurrentLbo = FatGetLboFromIndex( Vcb,
> FcbOrDcb->FirstClusterOfFile );
> -            FirstVboOfCurrentRun = CurrentVbo;
> -            FirstLboOfCurrentRun = CurrentLbo;
> -
> -            Runs = 0;
> -
> -            DebugTrace( 0, Dbg, "First Lbo of file = %8lx\n", CurrentLbo);
> -        }
> -    }
> -
> -    //
> -    //  Now we know that we are looking up a valid Vbo, but it is
> -    //  not in the Mcb, which is a monotonically increasing list of
> -    //  Vbo's.  Thus we have to go to the Fat, and update
> -    //  the Mcb as we go.  We use a try-finally to unpin the page
> -    //  of fat hanging around.  Also we mark *Allocated = FALSE, so that
> -    //  the caller wont try to use the data if we hit an exception.
> -    //
> -
> -    *Allocated = FALSE;
> -
> -    _SEH2_TRY {
> -
> -        FatEntry = (FAT_ENTRY)FatGetIndexFromLbo( Vcb, CurrentLbo );
> -
> -        //
> -        //  ASSERT that CurrentVbo and CurrentLbo are now cluster
> alligned.
> -        //  The assumption here, is that only whole clusters of Vbos and
> Lbos
> -        //  are mapped in the Mcb.
> -        //
> -
> -        ASSERT( ((CurrentLbo - Vcb->AllocationSupport.FileAreaLbo)
> -                                                    % BytesPerCluster ==
> 0) &&
> -                (CurrentVbo % BytesPerCluster == 0) );
> -
> -        //
> -        //  Starting from the first Vbo after the last Mcb entry, scan
> through
> -        //  the Fat looking for our Vbo. We continue through the Fat
> until we
> -        //  hit a noncontiguity beyond the desired Vbo, or the last
> cluster.
> -        //
> -
> -        while ( !LastCluster ) {
> -
> -            //
> -            //  Get the next fat entry, and update our Current variables.
> -            //
> -
> -#ifndef __REACTOS__
> -            FatLookupFatEntry( IrpContext, Vcb, FatEntry, &FatEntry,
> &Context );
> -#else
> -            FatLookupFatEntry( IrpContext, Vcb, FatEntry,
> (PULONG)&FatEntry, &Context );
> -#endif
> -
> -            PriorLbo = CurrentLbo;
> -            CurrentLbo = FatGetLboFromIndex( Vcb, FatEntry );
> -            CurrentVbo += BytesPerCluster;
> -
> -            switch ( FatInterpretClusterType( Vcb, FatEntry )) {
> -
> -            //
> -            //  Check for a break in the Fat allocation chain.
> -            //
> -
> -            case FatClusterAvailable:
> -            case FatClusterReserved:
> -            case FatClusterBad:
> -
> -                DebugTrace( 0, Dbg, "Break in allocation chain, entry =
> %d\n", FatEntry);
> -                DebugTrace(-1, Dbg, "FatLookupFileAllocation -> Fat
> Corrupt.  Raise Status.\n", 0);
> -
> -                FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
> -                FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
> -                break;
> -
> -            //
> -            //  If this is the last cluster, we must update the Mcb and
> -            //  exit the loop.
> -            //
> -
> -            case FatClusterLast:
> -
> -                //
> -                //  Assert we know where the current run started.  If the
> -                //  Mcb was empty when we were called,
> thenFirstLboOfCurrentRun
> -                //  was set to the start of the file.  If the Mcb
> contained an
> -                //  entry, then FirstLboOfCurrentRun was set on the first
> -                //  iteration through the loop.  Thus if
> FirstLboOfCurrentRun
> -                //  is 0, then there was an Mcb entry and we are on our
> first
> -                //  iteration, meaing that the last cluster in the Mcb was
> -                //  really the last allocated cluster, but we checked Vbo
> -                //  against AllocationSize, and found it OK, thus
> AllocationSize
> -                //  must be too large.
> -                //
> -                //  Note that, when we finally arrive here, CurrentVbo is
> actually
> -                //  the first Vbo beyond the file allocation and
> CurrentLbo is
> -                //  meaningless.
> -                //
> -
> -                DebugTrace( 0, Dbg, "Read last cluster of file.\n", 0);
> -
> -                //
> -                //  Detect the case of the maximal file.  Note that this
> really isn't
> -                //  a proper Vbo - those are zero-based, and this is a
> one-based number.
> -                //  The maximal file, of 2^32 - 1 bytes, has a maximum
> byte offset of
> -                //  2^32 - 2.
> -                //
> -                //  Just so we don't get confused here.
> -                //
> -
> -                if (CurrentVbo == 0) {
> -
> -                    *EndOnMax = TRUE;
> -                    CurrentVbo -= 1;
> -                }
> -
> -                LastCluster = TRUE;
> -
> -                if (FirstLboOfCurrentRun != 0 ) {
> -
> -                    DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n", 0);
> -                    DebugTrace( 0, Dbg, "  Vbo    = %08lx.\n",
> FirstVboOfCurrentRun);
> -                    DebugTrace( 0, Dbg, "  Lbo    = %08lx.\n",
> FirstLboOfCurrentRun);
> -                    DebugTrace( 0, Dbg, "  Length = %08lx.\n", CurrentVbo
> - FirstVboOfCurrentRun);
> -
> -                    (VOID)FatAddMcbEntry( Vcb,
> -                                          &FcbOrDcb->Mcb,
> -                                          FirstVboOfCurrentRun,
> -                                          FirstLboOfCurrentRun,
> -                                          CurrentVbo -
> FirstVboOfCurrentRun );
> -
> -                    Runs += 1;
> -                }
> -
> -                //
> -                //  Being at the end of allocation, make sure we have
> found
> -                //  the Vbo.  If we haven't, seeing as we checked VBO
> -                //  against AllocationSize, the real disk allocation is
> less
> -                //  than that of AllocationSize.  This comes about when
> the
> -                //  real allocation is not yet known, and AllocaitonSize
> -                //  contains MAXULONG.
> -                //
> -                //  KLUDGE! - If we were called by
> FatLookupFileAllocationSize
> -                //  Vbo is set to MAXULONG - 1, and AllocationSize to the
> lookup
> -                //  hint. Thus we merrily go along looking for a match
> that isn't
> -                //  there, but in the meantime building an Mcb.  If this
> is
> -                //  the case, fill in AllocationSize and return.
> -                //
> -
> -                if ( Vbo == MAXULONG - 1 ) {
> -
> -                    *Allocated = FALSE;
> -                    FcbOrDcb->Header.AllocationSize.QuadPart =
> CurrentVbo;
> -
> -                    DebugTrace( 0, Dbg, "New file allocation size =
> %08lx.\n", CurrentVbo);
> -                    try_return ( NOTHING );
> -                }
> -
> -                //
> -                //  We will lie ever so slightly if we really terminated
> on the
> -                //  maximal byte of a file.  It is really allocated.
> -                //
> -
> -                if (Vbo >= CurrentVbo && !*EndOnMax) {
> -
> -                    *Allocated = FALSE;
> -                    try_return ( NOTHING );
> -                }
> -
> -                break;
> -
> -            //
> -            //  This is a continuation in the chain.  If the run has a
> -            //  discontiguity at this point, update the Mcb, and if we
> are beyond
> -            //  the desired Vbo, this is the end of the run, so set
> LastCluster
> -            //  and exit the loop.
> -            //
> -
> -            case FatClusterNext:
> -
> -                //
> -                //  This is the loop check.  The Vbo must not be bigger
> than the size of
> -                //  the volume, and the Vbo must not have a) wrapped and
> b) not been at the
> -                //  very last cluster in the chain, for the case of the
> maximal file.
> -                //
> -
> -                if ( CurrentVbo == 0 ||
> -                     (BytesOnVolume.HighPart == 0 && CurrentVbo >
> BytesOnVolume.LowPart)) {
> -
> -                    FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
> -                    FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR
> );
> -                }
> -
> -                if ( PriorLbo + BytesPerCluster != CurrentLbo ) {
> -
> -                    //
> -                    //  Note that on the first time through the loop
> -                    //  (FirstLboOfCurrentRun == 0), we don't add the
> -                    //  run to the Mcb since it curresponds to the last
> -                    //  run already stored in the Mcb.
> -                    //
> -
> -                    if ( FirstLboOfCurrentRun != 0 ) {
> -
> -                        DebugTrace( 0, Dbg, "Adding a run to the Mcb.\n",
> 0);
> -                        DebugTrace( 0, Dbg, "  Vbo    = %08lx.\n",
> FirstVboOfCurrentRun);
> -                        DebugTrace( 0, Dbg, "  Lbo    = %08lx.\n",
> FirstLboOfCurrentRun);
> -                        DebugTrace( 0, Dbg, "  Length = %08lx.\n",
> CurrentVbo - FirstVboOfCurrentRun);
> -
> -                        FatAddMcbEntry( Vcb,
> -                                        &FcbOrDcb->Mcb,
> -                                        FirstVboOfCurrentRun,
> -                                        FirstLboOfCurrentRun,
> -                                        CurrentVbo - FirstVboOfCurrentRun
> );
> -
> -                        Runs += 1;
> -                    }
> -
> -                    //
> -                    //  Since we are at a run boundry, with CurrentLbo and
> -                    //  CurrentVbo being the first cluster of the next
> run,
> -                    //  we see if the run we just added encompases the
> desired
> -                    //  Vbo, and if so exit.  Otherwise we set up two new
> -                    //  First*boOfCurrentRun, and continue.
> -                    //
> -
> -                    if (CurrentVbo > Vbo) {
> -
> -                        LastCluster = TRUE;
> -
> -                    } else {
> -
> -                        FirstVboOfCurrentRun = CurrentVbo;
> -                        FirstLboOfCurrentRun = CurrentLbo;
> -                    }
> -                }
> -                break;
> -
> -            default:
> -
> -                DebugTrace(0, Dbg, "Illegal Cluster Type.\n", FatEntry);
> -
> -                FatBugCheck( 0, 0, 0 );
> -
> -                break;
> -
> -            } // switch()
> -        } // while()
> -
> -        //
> -        //  Load up the return parameters.
> -        //
> -        //  On exit from the loop, Vbo still contains the desired Vbo, and
> -        //  CurrentVbo is the first byte after the run that contained the
> -        //  desired Vbo.
> -        //
> -
> -        *Allocated = TRUE;
> -
> -        *Lbo = FirstLboOfCurrentRun + (Vbo - FirstVboOfCurrentRun);
> -
> -        *ByteCount = CurrentVbo - Vbo;
> -
> -        if (ARGUMENT_PRESENT(Index)) {
> -
> -            //
> -            //  Note that Runs only needs to be accurate with respect to
> where we
> -            //  ended.  Since partial-lookup cases will occur without
> exclusive
> -            //  synchronization, the Mcb itself may be much bigger by now.
> -            //
> -
> -            *Index = Runs - 1;
> -        }
> -
> -    try_exit: NOTHING;
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatLookupFileAllocation );
> -
> -        //
> -        //  We are done reading the Fat, so unpin the last page of fat
> -        //  that is hanging around
> -        //
> -
> -        FatUnpinBcb( IrpContext, Context.Bcb );
> -
> -        DebugTrace(-1, Dbg, "FatLookupFileAllocation -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatAddFileAllocation (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PFCB FcbOrDcb,
> -    IN PFILE_OBJECT FileObject OPTIONAL,
> -    IN ULONG DesiredAllocationSize
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine adds additional allocation to the specified
> file/directory.
> -    Additional allocation is added by appending clusters to the
> file/directory.
> -
> -    If the file already has a sufficient allocation then this procedure
> -    is effectively a noop.
> -
> -Arguments:
> -
> -    FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being modified.
> -               This parameter must not specify the root dcb.
> -
> -    FileObject - If supplied inform the cache manager of the change.
> -
> -    DesiredAllocationSize - Supplies the minimum size, in bytes, that we
> want
> -                            allocated to the file/directory.
> -
> ---*/
> -
> -{
> -    PVCB Vcb;
> -    LARGE_MCB NewMcb;
> -    PLARGE_MCB McbToCleanup = NULL;
> -    PDIRENT Dirent = NULL;
> -    ULONG NewAllocation;
> -    PBCB Bcb = NULL;
> -    BOOLEAN UnwindWeAllocatedDiskSpace = FALSE;
> -    BOOLEAN UnwindAllocationSizeSet = FALSE;
> -    BOOLEAN UnwindCacheManagerInformed = FALSE;
> -    BOOLEAN UnwindWeInitializedMcb = FALSE;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatAddFileAllocation\n", 0);
> -    DebugTrace( 0, Dbg, "  FcbOrDcb  =             %8lx\n", FcbOrDcb);
> -    DebugTrace( 0, Dbg, "  DesiredAllocationSize = %8lx\n",
> DesiredAllocationSize);
> -
> -    //
> -    //  If we haven't yet set the correct AllocationSize, do so.
> -    //
> -
> -    if (FcbOrDcb->Header.AllocationSize.QuadPart ==
> FCB_LOOKUP_ALLOCATIONSIZE_HINT)  {
> -
> -        FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
> -    }
> -
> -    //
> -    //  Check for the benign case that the desired allocation is already
> -    //  within the allocation size.
> -    //
> -
> -    if (DesiredAllocationSize <= FcbOrDcb->Header.AllocationSize.LowPart)
> {
> -
> -        DebugTrace(0, Dbg, "Desired size within current allocation.\n",
> 0);
> -
> -        DebugTrace(-1, Dbg, "FatAddFileAllocation -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    DebugTrace( 0, Dbg, "InitialAllocation = %08lx.\n", FcbOrDcb->Header.
> AllocationSize.LowPart);
> -
> -    //
> -    //  Get a chunk of disk space that will fullfill our needs.  If there
> -    //  was no initial allocation, start from the hint in the Vcb,
> otherwise
> -    //  try to allocate from the cluster after the initial allocation.
> -    //
> -    //  If there was no initial allocation to the file, we can just use
> the
> -    //  Mcb in the FcbOrDcb, otherwise we have to use a new one, and merge
> -    //  it to the one in the FcbOrDcb.
> -    //
> -
> -    Vcb = FcbOrDcb->Vcb;
> -
> -    _SEH2_TRY {
> -
> -        if (FcbOrDcb->Header.AllocationSize.LowPart == 0) {
> -
> -            LBO FirstLboOfFile;
> -
> -            ASSERT( FcbOrDcb->FcbCondition == FcbGood );
> -
> -            FatGetDirentFromFcbOrDcb( IrpContext,
> -                                      FcbOrDcb,
> -                                      &Dirent,
> -                                      &Bcb );
> -
> -            ASSERT( Bcb != NULL );
> -
> -            //
> -            //  Set this dirty right now since this call can fail.
> -            //
> -
> -            FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
> -
> -
> -            FatAllocateDiskSpace( IrpContext,
> -                                  Vcb,
> -                                  0,
> -                                  &DesiredAllocationSize,
> -                                  FALSE,
> -                                  &FcbOrDcb->Mcb );
> -
> -            UnwindWeAllocatedDiskSpace = TRUE;
> -            McbToCleanup = &FcbOrDcb->Mcb;
> -
> -            //
> -            //  We have to update the dirent and FcbOrDcb copies of
> -            //  FirstClusterOfFile since before it was 0
> -            //
> -
> -            FatLookupMcbEntry( FcbOrDcb->Vcb,
> -                               &FcbOrDcb->Mcb,
> -                               0,
> -                               &FirstLboOfFile,
> -                               (PULONG)NULL,
> -                               NULL );
> -
> -            DebugTrace( 0, Dbg, "First Lbo of file will be %08lx.\n",
> FirstLboOfFile );
> -
> -            FcbOrDcb->FirstClusterOfFile = FatGetIndexFromLbo( Vcb,
> FirstLboOfFile );
> -
> -            Dirent->FirstClusterOfFile = (USHORT)FcbOrDcb->
> FirstClusterOfFile;
> -
> -            if ( FatIsFat32(Vcb) ) {
> -
> -                Dirent->FirstClusterOfFileHi = (USHORT)(FcbOrDcb->FirstClusterOfFile
> >> 16);
> -            }
> -
> -            //
> -            //   Note the size of the allocation we need to tell the
> cache manager about.
> -            //
> -
> -            NewAllocation = DesiredAllocationSize;
> -
> -        } else {
> -
> -            LBO LastAllocatedLbo;
> -            VBO DontCare;
> -
> -            //
> -            //  Get the first cluster following the current allocation.
> It is possible
> -            //  the Mcb is empty (or short, etc.) so we need to be
> slightly careful
> -            //  about making sure we don't lie with the hint.
> -            //
> -
> -            (void)FatLookupLastMcbEntry( FcbOrDcb->Vcb, &FcbOrDcb->Mcb,
> &DontCare, &LastAllocatedLbo, NULL );
> -
> -            //
> -            //  Try to get some disk space starting from there.
> -            //
> -
> -            NewAllocation = DesiredAllocationSize - FcbOrDcb->Header.
> AllocationSize.LowPart;
> -
> -            FsRtlInitializeLargeMcb( &NewMcb, PagedPool );
> -            UnwindWeInitializedMcb = TRUE;
> -            McbToCleanup = &NewMcb;
> -
> -            FatAllocateDiskSpace( IrpContext,
> -                                  Vcb,
> -                                  (LastAllocatedLbo != ~0  ?
> -                                   FatGetIndexFromLbo(Vcb,LastAllocatedLbo
> + 1) :
> -                                   0),
> -                                  &NewAllocation,
> -                                  FALSE,
> -                                  &NewMcb );
> -
> -            UnwindWeAllocatedDiskSpace = TRUE;
> -        }
> -
> -        //
> -        //  Now that we increased the allocation of the file, mark it in
> the
> -        //  FcbOrDcb.  Carefully prepare to handle an inability to grow
> the cache
> -        //  structures.
> -        //
> -
> -        FcbOrDcb->Header.AllocationSize.LowPart += NewAllocation;
> -
> -        //
> -        //  Handle the maximal file case, where we may have just
> wrapped.  Note
> -        //  that this must be the precise boundary case wrap, i.e. by one
> byte,
> -        //  so that the new allocation is actually one byte "less" as far
> as we're
> -        //  concerned.  This is important for the extension case.
> -        //
> -
> -        if (FcbOrDcb->Header.AllocationSize.LowPart == 0) {
> -
> -            NewAllocation -= 1;
> -            FcbOrDcb->Header.AllocationSize.LowPart = 0xffffffff;
> -        }
> -
> -        UnwindAllocationSizeSet = TRUE;
> -
> -        //
> -        //  Inform the cache manager to increase the section size
> -        //
> -
> -        if ( ARGUMENT_PRESENT(FileObject) && CcIsFileCached(FileObject) )
> {
> -
> -            CcSetFileSizes( FileObject,
> -                            (PCC_FILE_SIZES)&FcbOrDcb->Header.AllocationSize
> );
> -            UnwindCacheManagerInformed = TRUE;
> -        }
> -
> -        //
> -        //  In the extension case, we have held off actually gluing the
> new
> -        //  allocation onto the file.  This simplifies exception cleanup
> since
> -        //  if it was already added and the section grow failed, we'd
> have to
> -        //  do extra work to unglue it.  This way, we can assume that if
> we
> -        //  raise the only thing we need to do is deallocate the disk
> space.
> -        //
> -        //  Merge the allocation now.
> -        //
> -
> -        if (FcbOrDcb->Header.AllocationSize.LowPart != NewAllocation) {
> -
> -            //
> -            //  Tack the new Mcb onto the end of the FcbOrDcb one.
> -            //
> -
> -            FatMergeAllocation( IrpContext,
> -                                Vcb,
> -                                &FcbOrDcb->Mcb,
> -                                &NewMcb );
> -        }
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatAddFileAllocation );
> -
> -        //
> -        //  Give FlushFileBuffer a clue here.
> -        //
> -
> -        SetFlag(FcbOrDcb->FcbState, FCB_STATE_FLUSH_FAT);
> -
> -        //
> -        //  If we were dogged trying to complete this operation, we need
> to go
> -        //  back various things out.
> -        //
> -
> -        if (_SEH2_AbnormalTermination()) {
> -
> -            //
> -            //  Pull off the allocation size we tried to add to this
> object if
> -            //  we failed to grow cache structures or Mcb structures.
> -            //
> -
> -            if (UnwindAllocationSizeSet) {
> -
> -                FcbOrDcb->Header.AllocationSize.LowPart -= NewAllocation;
> -            }
> -
> -            if (UnwindCacheManagerInformed) {
> -
> -                CcSetFileSizes( FileObject,
> -                                (PCC_FILE_SIZES)&FcbOrDcb->Header.AllocationSize
> );
> -            }
> -
> -            //
> -            //  In the case of initial allocation, we used the Fcb's Mcb
> and have
> -            //  to clean that up as well as the FAT chain references.
> -            //
> -
> -            if (FcbOrDcb->Header.AllocationSize.LowPart == 0) {
> -
> -                if (Dirent != NULL) {
> -
> -                    FcbOrDcb->FirstClusterOfFile = 0;
> -                    Dirent->FirstClusterOfFile = 0;
> -
> -                    if ( FatIsFat32(Vcb) ) {
> -
> -                        Dirent->FirstClusterOfFileHi = 0;
> -                    }
> -                }
> -            }
> -
> -            //
> -            //  ... and drop the dirent Bcb if we got it.  Do it now
> -            //  so we can afford to take the exception if we have to.
> -            //
> -
> -            FatUnpinBcb( IrpContext, Bcb );
> -
> -            _SEH2_TRY {
> -
> -                //
> -                //  Note this can re-raise.
> -                //
> -
> -                if ( UnwindWeAllocatedDiskSpace ) {
> -
> -                    FatDeallocateDiskSpace( IrpContext, Vcb, McbToCleanup
> );
> -                }
> -
> -            } _SEH2_FINALLY {
> -
> -                //
> -                //  We always want to clean up the non-initial allocation
> temporary Mcb,
> -                //  otherwise we have the Fcb's Mcb and we just truncate
> it away.
> -                //
> -
> -                if (UnwindWeInitializedMcb == TRUE) {
> -
> -                    //
> -                    //  Note that we already know a raise is in
> progress.  No danger
> -                    //  of encountering the normal case code below and
> doing this again.
> -                    //
> -
> -                    FsRtlUninitializeLargeMcb( McbToCleanup );
> -
> -                } else {
> -
> -                    if (McbToCleanup) {
> -
> -                        FsRtlTruncateLargeMcb( McbToCleanup, 0 );
> -                    }
> -                }
> -            } _SEH2_END;
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatAddFileAllocation -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    //
> -    //  Non-exceptional cleanup we always want to do.  In handling the
> re-raise possibilities
> -    //  during exceptions we had to make sure these two steps always
> happened there beforehand.
> -    //  So now we handle the usual case.
> -    //
> -
> -    FatUnpinBcb( IrpContext, Bcb );
> -
> -    if (UnwindWeInitializedMcb == TRUE) {
> -
> -        FsRtlUninitializeLargeMcb( &NewMcb );
> -    }
> -}
> -
> -
> -VOID
> -FatTruncateFileAllocation (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PFCB FcbOrDcb,
> -    IN ULONG DesiredAllocationSize
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine truncates the allocation to the specified file/directory.
> -
> -    If the file is already smaller than the indicated size then this
> procedure
> -    is effectively a noop.
> -
> -
> -Arguments:
> -
> -    FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being modified
> -               This parameter must not specify the root dcb.
> -
> -    DesiredAllocationSize - Supplies the maximum size, in bytes, that we
> want
> -                            allocated to the file/directory.  It is
> rounded
> -                            up to the nearest cluster.
> -
> -Return Value:
> -
> -    VOID - TRUE if the operation completed and FALSE if it had to
> -        block but could not.
> -
> ---*/
> -
> -{
> -    PVCB Vcb;
> -    PBCB Bcb = NULL;
> -    LARGE_MCB RemainingMcb;
> -    ULONG BytesPerCluster;
> -    PDIRENT Dirent = NULL;
> -    BOOLEAN UpdatedDirent = FALSE;
> -
> -    ULONG UnwindInitialAllocationSize;
> -    ULONG UnwindInitialFirstClusterOfFile;
> -    BOOLEAN UnwindWeAllocatedMcb = FALSE;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatTruncateFileAllocation\n", 0);
> -    DebugTrace( 0, Dbg, "  FcbOrDcb  =             %8lx\n", FcbOrDcb);
> -    DebugTrace( 0, Dbg, "  DesiredAllocationSize = %8lx\n",
> DesiredAllocationSize);
> -
> -    //
> -    //  If the Fcb isn't in good condition, we have no business whacking
> around on
> -    //  the disk after "its" clusters.
> -    //
> -    //  Inspired by a Prefix complaint.
> -    //
> -
> -    ASSERT( FcbOrDcb->FcbCondition == FcbGood );
> -
> -    //
> -    //  If we haven't yet set the correct AllocationSize, do so.
> -    //
> -
> -    if (FcbOrDcb->Header.AllocationSize.QuadPart ==
> FCB_LOOKUP_ALLOCATIONSIZE_HINT)  {
> -
> -        FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
> -    }
> -
> -    //
> -    //  Round up the Desired Allocation Size to the next cluster size
> -    //
> -
> -    Vcb = FcbOrDcb->Vcb;
> -
> -    BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
> -
> -    //
> -    //  Note if the desired allocation is zero, to distinguish this from
> -    //  the wrap case below.
> -    //
> -
> -    if (DesiredAllocationSize != 0) {
> -
> -        DesiredAllocationSize = (DesiredAllocationSize + (BytesPerCluster
> - 1)) &
> -                                ~(BytesPerCluster - 1);
> -        //
> -        //  Check for the benign case that the file is already smaller
> than
> -        //  the desired truncation.  Note that if it wraps, then a) it was
> -        //  specifying an offset in the maximally allocatable cluster and
> -        //  b) we're not asking to extend the file, either.  So stop.
> -        //
> -
> -        if (DesiredAllocationSize == 0 ||
> -            DesiredAllocationSize >= FcbOrDcb->Header.AllocationSize.LowPart)
> {
> -
> -            DebugTrace(0, Dbg, "Desired size within current
> allocation.\n", 0);
> -
> -            DebugTrace(-1, Dbg, "FatTruncateFileAllocation -> (VOID)\n",
> 0);
> -            return;
> -        }
> -
> -    }
> -
> -    UnwindInitialAllocationSize = FcbOrDcb->Header.
> AllocationSize.LowPart;
> -    UnwindInitialFirstClusterOfFile = FcbOrDcb->FirstClusterOfFile;
> -
> -    //
> -    //  Update the FcbOrDcb allocation size.  If it is now zero, we have
> the
> -    //  additional task of modifying the FcbOrDcb and Dirent copies of
> -    //  FirstClusterInFile.
> -    //
> -    //  Note that we must pin the dirent before actually deallocating the
> -    //  disk space since, in unwind, it would not be possible to
> reallocate
> -    //  deallocated disk space as someone else may have reallocated it and
> -    //  may cause an exception when you try to get some more disk space.
> -    //  Thus FatDeallocateDiskSpace must be the final dangerous operation.
> -    //
> -
> -    _SEH2_TRY {
> -
> -        FcbOrDcb->Header.AllocationSize.QuadPart = DesiredAllocationSize;
> -
> -        //
> -        //  Special case 0
> -        //
> -
> -        if (DesiredAllocationSize == 0) {
> -
> -            //
> -            //  We have to update the dirent and FcbOrDcb copies of
> -            //  FirstClusterOfFile since before it was 0
> -            //
> -
> -            ASSERT( FcbOrDcb->FcbCondition == FcbGood );
> -
> -            FatGetDirentFromFcbOrDcb( IrpContext, FcbOrDcb, &Dirent, &Bcb
> );
> -
> -            ASSERT( Dirent && Bcb );
> -
> -            Dirent->FirstClusterOfFile = 0;
> -
> -            if (FatIsFat32(Vcb)) {
> -
> -                Dirent->FirstClusterOfFileHi = 0;
> -            }
> -
> -            FcbOrDcb->FirstClusterOfFile = 0;
> -
> -            FatSetDirtyBcb( IrpContext, Bcb, Vcb, TRUE );
> -            UpdatedDirent = TRUE;
> -
> -            FatDeallocateDiskSpace( IrpContext, Vcb, &FcbOrDcb->Mcb );
> -
> -            FatRemoveMcbEntry( FcbOrDcb->Vcb, &FcbOrDcb->Mcb, 0,
> 0xFFFFFFFF );
> -
> -        } else {
> -
> -            //
> -            //  Split the existing allocation into two parts, one we will
> keep, and
> -            //  one we will deallocate.
> -            //
> -
> -            FsRtlInitializeLargeMcb( &RemainingMcb, PagedPool );
> -            UnwindWeAllocatedMcb = TRUE;
> -
> -            FatSplitAllocation( IrpContext,
> -                                Vcb,
> -                                &FcbOrDcb->Mcb,
> -                                DesiredAllocationSize,
> -                                &RemainingMcb );
> -
> -            FatDeallocateDiskSpace( IrpContext, Vcb, &RemainingMcb );
> -
> -            FsRtlUninitializeLargeMcb( &RemainingMcb );
> -        }
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatTruncateFileAllocation );
> -
> -        //
> -        //  Is this really the right backout strategy?  It would be nice
> if we could
> -        //  pretend the truncate worked if we knew that the file had
> gotten into
> -        //  a consistent state.  Leaving dangled clusters is probably
> quite preferable.
> -        //
> -
> -        if ( _SEH2_AbnormalTermination() ) {
> -
> -            FcbOrDcb->Header.AllocationSize.LowPart =
> UnwindInitialAllocationSize;
> -
> -            if ( (DesiredAllocationSize == 0) && (Dirent != NULL)) {
> -
> -                if (UpdatedDirent)  {
> -
> -                    //
> -                    //  If the dirent has been updated ok and marked
> dirty,  then we
> -                    //  failed in deallocatediscspace,  and don't know
> what state
> -                    //  the on disc fat chain is in.  So we throw away
> the mcb,
> -                    //  and potentially loose a few clusters until the
> next
> -                    //  chkdsk.  The operation has succeeded,  but the
> exception
> -                    //  will still propogate.  5.1
> -                    //
> -
> -                    FatRemoveMcbEntry( Vcb, &FcbOrDcb->Mcb, 0, 0xFFFFFFFF
> );
> -                    FcbOrDcb->Header.AllocationSize.QuadPart = 0;
> -                }
> -                else  {
> -
> -                    Dirent->FirstClusterOfFile = (USHORT)
> UnwindInitialFirstClusterOfFile;
> -
> -                    if ( FatIsFat32(Vcb) ) {
> -
> -                        Dirent->FirstClusterOfFileHi =
> -                                (USHORT)(UnwindInitialFirstClusterOfFile
> >> 16);
> -                    }
> -
> -                    FcbOrDcb->FirstClusterOfFile =
> UnwindInitialFirstClusterOfFile;
> -                }
> -            }
> -
> -            if ( UnwindWeAllocatedMcb ) {
> -
> -                FsRtlUninitializeLargeMcb( &RemainingMcb );
> -            }
> -
> -            //
> -            //  Note that in the non zero truncation case,  we will also
> -            //  leak clusters.  However, apart from this, the in memory
> and on disc
> -            //  structures will agree.
> -        }
> -
> -        FatUnpinBcb( IrpContext, Bcb );
> -
> -        //
> -        //  Give FlushFileBuffer a clue here.
> -        //
> -
> -        SetFlag(FcbOrDcb->FcbState, FCB_STATE_FLUSH_FAT);
> -
> -        DebugTrace(-1, Dbg, "FatTruncateFileAllocation -> (VOID)\n", 0);
> -    } _SEH2_END;
> -}
> -
> -
> -VOID
> -FatLookupFileAllocationSize (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PFCB FcbOrDcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine retrieves the current file allocatio size for the
> -    specified file/directory.
> -
> -Arguments:
> -
> -    FcbOrDcb - Supplies the Fcb/Dcb of the file/directory being modified
> -
> ---*/
> -
> -{
> -    LBO Lbo;
> -    ULONG ByteCount;
> -    BOOLEAN DontCare;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatLookupAllocationSize\n", 0);
> -    DebugTrace( 0, Dbg, "  FcbOrDcb  =      %8lx\n", FcbOrDcb);
> -
> -    //
> -    //  We call FatLookupFileAllocation with Vbo of 0xffffffff - 1.
> -    //
> -
> -    FatLookupFileAllocation( IrpContext,
> -                             FcbOrDcb,
> -                             MAXULONG - 1,
> -                             &Lbo,
> -                             &ByteCount,
> -                             &DontCare,
> -                             &DontCare,
> -                             NULL );
> -
> -    //
> -    //  FileSize was set at Fcb creation time from the contents of the
> directory entry,
> -    //  and we are only now looking up the real length of the allocation
> chain.  If it
> -    //  cannot be contained, this is trash.  Probably more where that
> came from.
> -    //
> -
> -    if (FcbOrDcb->Header.FileSize.LowPart > FcbOrDcb->Header.AllocationSize.LowPart)
> {
> -
> -        FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
> -        FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
> -    }
> -
> -    DebugTrace(-1, Dbg, "FatLookupFileAllocationSize -> (VOID)\n", 0);
> -    return;
> -}
> -
> -
> -VOID
> -FatAllocateDiskSpace (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG AbsoluteClusterHint,
> -    IN PULONG ByteCount,
> -    IN BOOLEAN ExactMatchRequired,
> -    OUT PLARGE_MCB Mcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This procedure allocates additional disk space and builds an mcb
> -    representing the newly allocated space.  If the space cannot be
> -    allocated then this procedure raises an appropriate status.
> -
> -    Searching starts from the hint index in the Vcb unless an alternative
> -    non-zero hint is given in AlternateClusterHint.  If we are using the
> -    hint field in the Vcb, it is set to the cluster following our
> allocation
> -    when we are done.
> -
> -    Disk space can only be allocated in cluster units so this procedure
> -    will round up any byte count to the next cluster boundary.
> -
> -    Pictorially what is done is the following (where ! denotes the end of
> -    the fat chain (i.e., FAT_CLUSTER_LAST)):
> -
> -
> -        Mcb (empty)
> -
> -    becomes
> -
> -        Mcb |--a--|--b--|--c--!
> -
> -                            ^
> -        ByteCount ----------+
> -
> -Arguments:
> -
> -    Vcb - Supplies the VCB being modified
> -
> -    AbsoluteClusterHint  - Supplies an alternate hint index to start the
> -                           search from.  If this is zero we use, and
> update,
> -                           the Vcb hint field.
> -
> -    ByteCount - Supplies the number of bytes that we are requesting, and
> -                receives the number of bytes that we got.
> -
> -    ExactMatchRequired - Caller should set this to TRUE if only the
> precise run requested
> -                 is acceptable.
> -
> -    Mcb - Receives the MCB describing the newly allocated disk space.  The
> -          caller passes in an initialized Mcb that is filled in by this
> procedure.
> -
> - Return Value:
> -
> -    TRUE  - Allocated ok
> -    FALSE - Failed to allocate exactly as requested (=>
> ExactMatchRequired was TRUE)
> -
> ---*/
> -
> -{
> -    UCHAR LogOfBytesPerCluster;
> -    ULONG BytesPerCluster;
> -    ULONG StartingCluster;
> -    ULONG ClusterCount;
> -    ULONG WindowRelativeHint;
> -#if DBG
> -#ifndef __REACTOS__
> -    ULONG i;
> -#endif
> -    ULONG PreviousClear;
> -#endif
> -
> -    PFAT_WINDOW Window;
> -    BOOLEAN Wait;
> -    BOOLEAN Result = TRUE;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatAllocateDiskSpace\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb        = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  *ByteCount = %8lx\n", *ByteCount);
> -    DebugTrace( 0, Dbg, "  Mcb        = %8lx\n", Mcb);
> -    DebugTrace( 0, Dbg, "  Hint       = %8lx\n", AbsoluteClusterHint);
> -
> -    ASSERT((AbsoluteClusterHint <= Vcb->AllocationSupport.NumberOfClusters
> + 2) && (1 != AbsoluteClusterHint));
> -
> -    //
> -    //  Make sure byte count is not zero
> -    //
> -
> -    if (*ByteCount == 0) {
> -
> -        DebugTrace(0, Dbg, "Nothing to allocate.\n", 0);
> -
> -        DebugTrace(-1, Dbg, "FatAllocateDiskSpace -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    //
> -    //  Compute the cluster count based on the byte count, rounding up
> -    //  to the next cluster if there is any remainder.  Note that the
> -    //  pathalogical case BytesCount == 0 has been eliminated above.
> -    //
> -
> -    LogOfBytesPerCluster = Vcb->AllocationSupport.LogOfBytesPerCluster;
> -    BytesPerCluster = 1 << LogOfBytesPerCluster;
> -
> -    *ByteCount = (*ByteCount + (BytesPerCluster - 1))
> -                            & ~(BytesPerCluster - 1);
> -
> -    //
> -    //  If ByteCount is NOW zero, then we were asked for the maximal
> -    //  filesize (or at least for bytes in the last allocatable sector).
> -    //
> -
> -    if (*ByteCount == 0) {
> -
> -        *ByteCount = 0xffffffff;
> -        ClusterCount =  1 << (32 - LogOfBytesPerCluster);
> -
> -    } else {
> -
> -        ClusterCount = (*ByteCount >> LogOfBytesPerCluster);
> -    }
> -
> -    //
> -    //  Make sure there are enough free clusters to start with, and
> -    //  take them now so that nobody else takes them from us.
> -    //
> -
> -    ExAcquireResourceSharedLite(&Vcb->ChangeBitMapResource, TRUE);
> -    FatLockFreeClusterBitMap( Vcb );
> -
> -    if (ClusterCount <= Vcb->AllocationSupport.NumberOfFreeClusters) {
> -
> -        Vcb->AllocationSupport.NumberOfFreeClusters -= ClusterCount;
> -
> -    } else {
> -
> -        FatUnlockFreeClusterBitMap( Vcb );
> -        ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -
> -        DebugTrace(0, Dbg, "Disk Full.  Raise Status.\n", 0);
> -        FatRaiseStatus( IrpContext, STATUS_DISK_FULL );
> -    }
> -
> -    //
> -    //  Did the caller supply a hint?
> -    //
> -
> -    if ((0 != AbsoluteClusterHint) && (AbsoluteClusterHint <
> (Vcb->AllocationSupport.NumberOfClusters + 2)))  {
> -
> -        if (Vcb->NumberOfWindows > 1)  {
> -
> -            //
> -            //  If we're being called upon to allocate clusters outside
> the
> -            //  current window (which happens only via MoveFile), it's a
> problem.
> -            //  We address this by changing the current window to be the
> one which
> -            //  contains the alternate cluster hint.  Note that if the
> user's
> -            //  request would cross a window boundary, he doesn't really
> get what
> -            //  he wanted.
> -            //
> -
> -            if (AbsoluteClusterHint < Vcb->CurrentWindow->FirstCluster ||
> -                AbsoluteClusterHint > Vcb->CurrentWindow->LastCluster) {
> -
> -                ULONG BucketNum = FatWindowOfCluster( AbsoluteClusterHint
> );
> -
> -                ASSERT( BucketNum < Vcb->NumberOfWindows);
> -
> -                //
> -                //  Drop our shared lock on the ChangeBitMapResource,
> and pick it up again
> -                //  exclusive in preparation for making the window swap.
> -                //
> -
> -                FatUnlockFreeClusterBitMap(Vcb);
> -                ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -                ExAcquireResourceExclusiveLite(&Vcb->ChangeBitMapResource,
> TRUE);
> -                FatLockFreeClusterBitMap(Vcb);
> -
> -                Window = &Vcb->Windows[BucketNum];
> -
> -                //
> -                //  Again,  test the current window against the one we
> want - some other
> -                //  thread could have sneaked in behind our backs and
> kindly set it to the one
> -                //  we need,  when we dropped and reacquired the
> ChangeBitMapResource above.
> -                //
> -
> -                if (Window != Vcb->CurrentWindow)  {
> -
> -                    _SEH2_TRY {
> -
> -                        Wait = BooleanFlagOn(IrpContext->Flags,
> IRP_CONTEXT_FLAG_WAIT);
> -                        SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
> -
> -                        //
> -                        //  Change to the new window (update
> Vcb->CurrentWindow) and scan it
> -                        //  to build up a freespace bitmap etc.
> -                        //
> -
> -                        FatExamineFatEntries( IrpContext, Vcb,
> -                                              0,
> -                                              0,
> -                                              FALSE,
> -                                              Window,
> -                                              NULL);
> -
> -                    } _SEH2_FINALLY {
> -
> -                        if (!Wait) {
> -
> -                            ClearFlag(IrpContext->Flags,
> IRP_CONTEXT_FLAG_WAIT);
> -                        }
> -
> -                        if (_SEH2_AbnormalTermination()) {
> -
> -                            //
> -                            //  We will have raised as a result of
> failing to pick up the
> -                            //  chunk of the FAT for this window move.
> Release our resources
> -                            //  and return the cluster count to the
> volume.
> -                            //
> -
> -                            Vcb->AllocationSupport.NumberOfFreeClusters
> += ClusterCount;
> -
> -                            FatUnlockFreeClusterBitMap( Vcb );
> -                            ExReleaseResourceLite(&Vcb->
> ChangeBitMapResource);
> -                        }
> -                    } _SEH2_END;
> -                }
> -            }
> -
> -            //
> -            //  Make the hint cluster number relative to the base of the
> current window...
> -            //
> -            //  Currentwindow->Firstcluster is baised by +2 already,  so
> we will lose the
> -            //  bias already in AbsoluteClusterHint.  Put it back....
> -            //
> -
> -            WindowRelativeHint = AbsoluteClusterHint -
> Vcb->CurrentWindow->FirstCluster + 2;
> -        }
> -        else {
> -
> -            //
> -            //  Only one 'window',  ie fat16/12.  No modification
> necessary.
> -            //
> -
> -            WindowRelativeHint = AbsoluteClusterHint;
> -        }
> -    }
> -    else {
> -
> -        //
> -        //  Either no hint supplied,  or it was out of range,  so grab
> one from the Vcb
> -        //
> -        //  NOTE: Clusterhint in the Vcb is not guaranteed to be set (may
> be -1)
> -        //
> -
> -        WindowRelativeHint = Vcb->ClusterHint;
> -        AbsoluteClusterHint = 0;
> -
> -        //
> -        //  Vcb hint may not have been initialized yet.  Force to valid
> cluster.
> -        //
> -
> -        if (-1 == WindowRelativeHint)  {
> -
> -            WindowRelativeHint = 2;
> -        }
> -    }
> -
> -    ASSERT((WindowRelativeHint >= 2) && (WindowRelativeHint <
> Vcb->FreeClusterBitMap.SizeOfBitMap + 2));
> -
> -    //
> -    //  Keep track of the window we're allocating from, so we can clean
> -    //  up correctly if the current window changes after we unlock the
> -    //  bitmap.
> -    //
> -
> -    Window = Vcb->CurrentWindow;
> -
> -    //
> -    //  Try to find a run of free clusters large enough for us.
> -    //
> -
> -    StartingCluster = FatFindFreeClusterRun( IrpContext,
> -                                             Vcb,
> -                                             ClusterCount,
> -                                             WindowRelativeHint );
> -    //
> -    //  If the above call was successful, we can just update the fat
> -    //  and Mcb and exit.  Otherwise we have to look for smaller free
> -    //  runs.
> -    //
> -    //  This test is a bit funky. Note that the error return from
> -    //  RtlFindClearBits is -1, and adding two to that is 1.
> -    //
> -
> -    if ((StartingCluster != 1) &&
> -        ((0 == AbsoluteClusterHint) || (StartingCluster ==
> WindowRelativeHint))
> -    )  {
> -
> -#if DBG
> -        PreviousClear = RtlNumberOfClearBits( &Vcb->FreeClusterBitMap );
> -#endif // DBG
> -
> -        //
> -        //  Take the clusters we found, and unlock the bit map.
> -        //
> -
> -        FatReserveClusters(IrpContext, Vcb, StartingCluster,
> ClusterCount);
> -
> -        Window->ClustersFree -= ClusterCount;
> -
> -        StartingCluster += Window->FirstCluster;
> -        StartingCluster -= 2;
> -
> -        ASSERT( PreviousClear - ClusterCount == Window->ClustersFree );
> -
> -        FatUnlockFreeClusterBitMap( Vcb );
> -
> -        //
> -        //  Note that this call will never fail since there is always
> -        //  room for one entry in an empty Mcb.
> -        //
> -
> -        FatAddMcbEntry( Vcb, Mcb,
> -                        0,
> -                        FatGetLboFromIndex( Vcb, StartingCluster ),
> -                        *ByteCount);
> -        _SEH2_TRY {
> -
> -            //
> -            //  Update the fat.
> -            //
> -
> -            FatAllocateClusters(IrpContext, Vcb,
> -                                StartingCluster,
> -                                ClusterCount);
> -
> -        } _SEH2_FINALLY {
> -
> -            DebugUnwind( FatAllocateDiskSpace );
> -
> -            //
> -            //  If the allocate clusters failed, remove the run from the
> Mcb,
> -            //  unreserve the clusters, and reset the free cluster count.
> -            //
> -
> -            if (_SEH2_AbnormalTermination()) {
> -
> -                FatRemoveMcbEntry( Vcb, Mcb, 0, *ByteCount );
> -
> -                FatLockFreeClusterBitMap( Vcb );
> -
> -                //  Only clear bits if the bitmap window is the same.
> -
> -                if (Window == Vcb->CurrentWindow) {
> -
> -                    //  Both values (startingcluster and
> window->firstcluster) are
> -                    //  already biased by 2,  so will cancel,  so we need
> to add in the 2 again.
> -
> -                    FatUnreserveClusters( IrpContext, Vcb,
> -                                          StartingCluster -
> Window->FirstCluster + 2,
> -                                          ClusterCount );
> -                }
> -
> -                Window->ClustersFree += ClusterCount;
> -                Vcb->AllocationSupport.NumberOfFreeClusters +=
> ClusterCount;
> -
> -                FatUnlockFreeClusterBitMap( Vcb );
> -            }
> -
> -            ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -        } _SEH2_END;
> -
> -    } else {
> -
> -        //
> -        //  Note that Index is a zero-based window-relative number.  When
> appropriate
> -        //  it'll get converted into a true cluster number and put in
> Cluster, which
> -        //  will be a volume relative true cluster number.
> -        //
> -
> -        ULONG Index;
> -        ULONG Cluster;
> -        ULONG CurrentVbo;
> -        ULONG PriorLastCluster;
> -        ULONG BytesFound;
> -
> -        ULONG ClustersFound = 0;
> -        ULONG ClustersRemaining;
> -
> -        BOOLEAN LockedBitMap = FALSE;
> -        BOOLEAN SelectNextContigWindow = FALSE;
> -
> -        //
> -        //  Drop our shared lock on the ChangeBitMapResource,  and pick
> it up again
> -        //  exclusive in preparation for making a window swap.
> -        //
> -
> -        FatUnlockFreeClusterBitMap(Vcb);
> -        ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -        ExAcquireResourceExclusiveLite(&Vcb->ChangeBitMapResource, TRUE);
> -        FatLockFreeClusterBitMap(Vcb);
> -        LockedBitMap = TRUE;
> -
> -        _SEH2_TRY {
> -
> -            if ( ExactMatchRequired && (1 == Vcb->NumberOfWindows))  {
> -
> -                //
> -                //  Give up right now,  there are no more windows to
> search!  RtlFindClearBits
> -                //  searchs the whole bitmap,  so we would have found any
> contiguous run
> -                //  large enough.
> -                //
> -
> -                try_leave( Result = FALSE);
> -            }
> -
> -            //
> -            //  While the request is still incomplete, look for the
> largest
> -            //  run of free clusters, mark them taken, allocate the run in
> -            //  the Mcb and Fat, and if this isn't the first time through
> -            //  the loop link it to prior run on the fat.  The Mcb will
> -            //  coalesce automatically.
> -            //
> -
> -            ClustersRemaining = ClusterCount;
> -            CurrentVbo = 0;
> -            PriorLastCluster = 0;
> -
> -            while (ClustersRemaining != 0) {
> -
> -                //
> -                //  If we just entered the loop, the bit map is already
> locked
> -                //
> -
> -                if ( !LockedBitMap ) {
> -
> -                    FatLockFreeClusterBitMap( Vcb );
> -                    LockedBitMap = TRUE;
> -                }
> -
> -                //
> -                //  Find the largest run of free clusters.  If the run is
> -                //  bigger than we need, only use what we need.  Note that
> -                //  this will then be the last while() iteration.
> -                //
> -
> -                // 12/3/95: need to bias bitmap by 2 bits for the defrag
> -                // hooks and the below macro became impossible to do
> without in-line
> -                // procedures.
> -                //
> -                // ClustersFound = FatLongestFreeClusterRun( IrpContext,
> Vcb, &Index );
> -
> -                ClustersFound = 0;
> -
> -                if (!SelectNextContigWindow)  {
> -
> -                    if ( 0 != WindowRelativeHint)  {
> -
> -                        ULONG Desired = Vcb->FreeClusterBitMap.SizeOfBitMap
> - (WindowRelativeHint - 2);
> -
> -                        //
> -                        //  We will try to allocate contiguously.  Try
> from the current hint the to
> -                        //  end of current window.  Don't try for more
> than we actually need.
> -                        //
> -
> -                        if (Desired > ClustersRemaining)  {
> -
> -                            Desired = ClustersRemaining;
> -                        }
> -
> -                        if (RtlAreBitsClear(  &Vcb->FreeClusterBitMap,
> -                                              WindowRelativeHint - 2,
> -                                              Desired))
> -                        {
> -                            //
> -                            //  Clusters from hint->...windowend are
> free.  Take them.
> -                            //
> -
> -                            Index = WindowRelativeHint - 2;
> -                            ClustersFound = Desired;
> -
> -                            if (FatIsFat32(Vcb))  {
> -
> -                                //
> -                                //  We're now up against the end of the
> current window,  so indicate that we
> -                                //  want the next window in the sequence
> next time around.  (If we're not up
> -                                //  against the end of the window,  then
> we got what we needed and won't be
> -                                //  coming around again anyway).
> -                                //
> -
> -                                SelectNextContigWindow = TRUE;
> -                                WindowRelativeHint = 2;
> -                            }
> -                            else {
> -
> -                                //
> -                                //  FAT 12/16 - we've run up against the
> end of the volume.  Clear the
> -                                //  hint,  since we now have no idea
> where to look.
> -                                //
> -
> -                                WindowRelativeHint = 0;
> -                            }
> -#if DBG
> -                            PreviousClear = RtlNumberOfClearBits(
> &Vcb->FreeClusterBitMap );
> -#endif // DBG
> -                        }
> -                        else  {
> -
> -                            if (ExactMatchRequired)  {
> -
> -                                //
> -                                //  If our caller required an exact
> match,  then we're hosed.  Bail out now.
> -                                //
> -
> -                                try_leave( Result = FALSE);
> -                            }
> -
> -                            //
> -                            //  Hint failed,  drop back to pot luck
> -                            //
> -
> -                            WindowRelativeHint = 0;
> -                        }
> -                    }
> -
> -                    if ((0 == WindowRelativeHint) && (0 ==
> ClustersFound)) {
> -
> -                        if (ClustersRemaining <= Vcb->CurrentWindow->ClustersFree)
> {
> -
> -                            //
> -                            //  The remaining allocation could be
> satisfied entirely from this
> -                            //  window.  We will ask only for what we
> need,  to try and avoid
> -                            //  unnecessarily fragmenting large runs of
> space by always using
> -                            //  (part of) the largest run we can find.
> This call will return the
> -                            //  first run large enough.
> -                            //
> -
> -                            Index = RtlFindClearBits(
> &Vcb->FreeClusterBitMap,  ClustersRemaining,  0);
> -
> -                            if (-1 != Index)  {
> -
> -                                ClustersFound = ClustersRemaining;
> -                            }
> -                        }
> -
> -                        if (0 == ClustersFound)  {
> -
> -                            //
> -                            //  Still nothing,  so just take the largest
> free run we can find.
> -                            //
> -
> -                            ClustersFound = RtlFindLongestRunClear(
> &Vcb->FreeClusterBitMap, &Index );
> -
> -                        }
> -#if DBG
> -                        PreviousClear = RtlNumberOfClearBits(
> &Vcb->FreeClusterBitMap );
> -#endif // DBG
> -                        if (ClustersFound >= ClustersRemaining) {
> -
> -                            ClustersFound = ClustersRemaining;
> -                        }
> -                        else {
> -
> -                            //
> -                            //  If we just ran up to the end of a
> window,  set up a hint that
> -                            //  we'd like the next consecutive window
> after this one. (FAT32 only)
> -                            //
> -
> -                            if ( ((Index + ClustersFound) ==
> Vcb->FreeClusterBitMap.SizeOfBitMap) &&
> -                                 FatIsFat32( Vcb)
> -                               )  {
> -
> -                                SelectNextContigWindow = TRUE;
> -                                WindowRelativeHint = 2;
> -                            }
> -                        }
> -                    }
> -                }
> -
> -                if (ClustersFound == 0) {
> -
> -                    ULONG FaveWindow = 0;
> -                    BOOLEAN SelectedWindow;
> -
> -                    //
> -                    //  If we found no free clusters on a single-window
> FAT,
> -                    //  there was a bad problem with the free cluster
> count.
> -                    //
> -
> -                    if (1 == Vcb->NumberOfWindows) {
> -
> -                        FatBugCheck( 0, 5, 0 );
> -                    }
> -
> -                    //
> -                    //  Switch to a new bucket.  Possibly the next one if
> we're
> -                    //  currently on a roll (allocating contiguously)
> -                    //
> -
> -                    SelectedWindow = FALSE;
> -
> -                    if ( SelectNextContigWindow)  {
> -
> -                        ULONG NextWindow;
> -
> -                        NextWindow = (((ULONG)((PUCHAR)Vcb->CurrentWindow
> - (PUCHAR)Vcb->Windows)) / sizeof( FAT_WINDOW)) + 1;
> -
> -                        if ((NextWindow < Vcb->NumberOfWindows) &&
> -                            ( Vcb->Windows[ NextWindow].ClustersFree > 0)
> -                           )  {
> -
> -                            FaveWindow = NextWindow;
> -                            SelectedWindow = TRUE;
> -                        }
> -                        else  {
> -
> -                            if (ExactMatchRequired)  {
> -
> -                                //
> -                                //  Some dope tried to allocate a run
> past the end of the volume...
> -                                //
> -
> -                                try_leave( Result = FALSE);
> -                            }
> -
> -                            //
> -                            //  Give up on the contiguous allocation
> attempts
> -                            //
> -
> -                            WindowRelativeHint = 0;
> -                        }
> -
> -                        SelectNextContigWindow = FALSE;
> -                    }
> -
> -                    if (!SelectedWindow)  {
> -
> -                        //
> -                        //  Select a new window to begin allocating from
> -                        //
> -
> -                        FaveWindow = FatSelectBestWindow( Vcb);
> -                    }
> -
> -                    //
> -                    //  By now we'd better have found a window with some
> free clusters
> -                    //
> -
> -                    if (0 == Vcb->Windows[ FaveWindow].ClustersFree) {
> -
> -                        FatBugCheck( 0, 5, 1 );
> -                    }
> -
> -                    Wait = BooleanFlagOn(IrpContext->Flags,
> IRP_CONTEXT_FLAG_WAIT);
> -                    SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
> -
> -                    FatExamineFatEntries( IrpContext, Vcb,
> -                                          0,
> -                                          0,
> -                                          FALSE,
> -                                          &Vcb->Windows[FaveWindow],
> -                                          NULL);
> -
> -                    if (!Wait) {
> -
> -                        ClearFlag(IrpContext->Flags,
> IRP_CONTEXT_FLAG_WAIT);
> -                    }
> -
> -                    //
> -                    //  Now we'll just go around the loop again, having
> switched windows,
> -                    //  and allocate....
> -                    //
> -#if DBG
> -                    PreviousClear = RtlNumberOfClearBits(
> &Vcb->FreeClusterBitMap );
> -#endif //DBG
> -                }       // if (clustersfound == 0)
> -                else  {
> -
> -                    //
> -                    //  Take the clusters we found, convert our index to
> a cluster number
> -                    //  and unlock the bit map.
> -                    //
> -
> -                    Window = Vcb->CurrentWindow;
> -
> -                    FatReserveClusters( IrpContext, Vcb, (Index + 2),
> ClustersFound );
> -
> -                    Cluster = Index + Window->FirstCluster;
> -
> -                    Window->ClustersFree -= ClustersFound;
> -                    ASSERT( PreviousClear - ClustersFound ==
> Window->ClustersFree );
> -
> -                    FatUnlockFreeClusterBitMap( Vcb );
> -                    LockedBitMap = FALSE;
> -
> -                    //
> -                    //  Add the newly alloced run to the Mcb.
> -                    //
> -
> -                    BytesFound = ClustersFound << LogOfBytesPerCluster;
> -
> -                    FatAddMcbEntry( Vcb, Mcb,
> -                                    CurrentVbo,
> -                                    FatGetLboFromIndex( Vcb, Cluster ),
> -                                    BytesFound );
> -
> -                    //
> -                    //  Connect the last allocated run with this one, and
> allocate
> -                    //  this run on the Fat.
> -                    //
> -
> -                    if (PriorLastCluster != 0) {
> -
> -                        FatSetFatEntry( IrpContext,
> -                                        Vcb,
> -                                        PriorLastCluster,
> -                                        (FAT_ENTRY)Cluster );
> -                    }
> -
> -                    //
> -                    //  Update the fat
> -                    //
> -
> -                    FatAllocateClusters( IrpContext, Vcb, Cluster,
> ClustersFound );
> -
> -                    //
> -                    //  Prepare for the next iteration.
> -                    //
> -
> -                    CurrentVbo += BytesFound;
> -                    ClustersRemaining -= ClustersFound;
> -                    PriorLastCluster = Cluster + ClustersFound - 1;
> -                }
> -            }  // while (clustersremaining)
> -
> -        } _SEH2_FINALLY {
> -
> -            DebugUnwind( FatAllocateDiskSpace );
> -
> -            ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -
> -            //
> -            //  Is there any unwinding to do?
> -            //
> -
> -            if ( _SEH2_AbnormalTermination() || (FALSE == Result)) {
> -
> -                //
> -                //  Flag to the caller that they're getting nothing
> -                //
> -
> -                *ByteCount = 0;
> -
> -                //
> -                //  There are three places we could have taken this
> exception:
> -                //  when switching the window (FatExamineFatEntries),
> adding
> -                //  a found run to the Mcb (FatAddMcbEntry), or when
> writing
> -                //  the changes to the FAT (FatSetFatEntry).  In the
> first case
> -                //  we don't have anything to unwind before deallocation,
> and
> -                //  can detect this by seeing if we have the ClusterBitmap
> -                //  mutex out.
> -
> -                if (!LockedBitMap) {
> -
> -                    FatLockFreeClusterBitMap( Vcb );
> -
> -                    //
> -                    //  In these cases, we have the possiblity that the
> FAT
> -                    //  window is still in place and we need to clear the
> bits.
> -                    //  If the Mcb entry isn't there (we raised trying to
> add
> -                    //  it), the effect of trying to remove it is a noop.
> -                    //
> -
> -                    if (Window == Vcb->CurrentWindow) {
> -
> -                        //
> -                        //  Cluster reservation works on cluster 2 based
> window-relative
> -                        //  numbers, so we must convert.  The subtraction
> will lose the
> -                        //  cluster 2 base, so bias the result.
> -                        //
> -
> -                        FatUnreserveClusters( IrpContext, Vcb,
> -                                              (Cluster -
> Window->FirstCluster) + 2,
> -                                              ClustersFound );
> -                    }
> -
> -                    //
> -                    //  Note that FatDeallocateDiskSpace will take care
> of adjusting
> -                    //  to account for the entries in the Mcb.  All we
> have to account
> -                    //  for is the last run that didn't make it.
> -                    //
> -
> -                    Window->ClustersFree += ClustersFound;
> -                    Vcb->AllocationSupport.NumberOfFreeClusters +=
> ClustersFound;
> -
> -                    FatUnlockFreeClusterBitMap( Vcb );
> -
> -                    FatRemoveMcbEntry( Vcb, Mcb, CurrentVbo, BytesFound );
> -
> -                } else {
> -
> -                    //
> -                    //  Just drop the mutex now - we didn't manage to do
> anything
> -                    //  that needs to be backed out.
> -                    //
> -
> -                    FatUnlockFreeClusterBitMap( Vcb );
> -                }
> -
> -                _SEH2_TRY {
> -
> -                    //
> -                    //  Now we have tidied up, we are ready to just send
> the Mcb
> -                    //  off to deallocate disk space
> -                    //
> -
> -                    FatDeallocateDiskSpace( IrpContext, Vcb, Mcb );
> -
> -                } _SEH2_FINALLY {
> -
> -                    //
> -                    //  Now finally (really), remove all the entries from
> the mcb
> -                    //
> -
> -                    FatRemoveMcbEntry( Vcb, Mcb, 0, 0xFFFFFFFF );
> -                } _SEH2_END;
> -            }
> -
> -            DebugTrace(-1, Dbg, "FatAllocateDiskSpace -> (VOID)\n", 0);
> -
> -        } _SEH2_END; // finally
> -    }
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatDeallocateDiskSpace (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN PLARGE_MCB Mcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This procedure deallocates the disk space denoted by an input
> -    mcb.  Note that the input MCB does not need to necessarily describe
> -    a chain that ends with a FAT_CLUSTER_LAST entry.
> -
> -    Pictorially what is done is the following
> -
> -        Fat |--a--|--b--|--c--|
> -        Mcb |--a--|--b--|--c--|
> -
> -    becomes
> -
> -        Fat |--0--|--0--|--0--|
> -        Mcb |--a--|--b--|--c--|
> -
> -Arguments:
> -
> -    Vcb - Supplies the VCB being modified
> -
> -    Mcb - Supplies the MCB describing the disk space to deallocate.  Note
> -          that Mcb is unchanged by this procedure.
> -
> -
> -Return Value:
> -
> -    None.
> -
> ---*/
> -
> -{
> -    LBO Lbo;
> -    VBO Vbo;
> -
> -    ULONG RunsInMcb;
> -    ULONG ByteCount;
> -    ULONG ClusterCount;
> -    ULONG ClusterIndex;
> -    ULONG McbIndex;
> -
> -    UCHAR LogOfBytesPerCluster;
> -
> -    PFAT_WINDOW Window;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatDeallocateDiskSpace\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  Mcb = %8lx\n", Mcb);
> -
> -    LogOfBytesPerCluster = Vcb->AllocationSupport.LogOfBytesPerCluster;
> -
> -    RunsInMcb = FsRtlNumberOfRunsInLargeMcb( Mcb );
> -
> -    if ( RunsInMcb == 0 ) {
> -
> -        DebugTrace(-1, Dbg, "FatDeallocateDiskSpace -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    _SEH2_TRY {
> -
> -        //
> -        //  Run though the Mcb, freeing all the runs in the fat.
> -        //
> -        //  We do this in two steps (first update the fat, then the bitmap
> -        //  (which can't fail)) to prevent other people from taking
> clusters
> -        //  that we need to re-allocate in the event of unwind.
> -        //
> -
> -        ExAcquireResourceSharedLite(&Vcb->ChangeBitMapResource, TRUE);
> -
> -        RunsInMcb = FsRtlNumberOfRunsInLargeMcb( Mcb );
> -
> -        for ( McbIndex = 0; McbIndex < RunsInMcb; McbIndex++ ) {
> -
> -            FatGetNextMcbEntry( Vcb, Mcb, McbIndex, &Vbo, &Lbo,
> &ByteCount );
> -
> -            //
> -            //  Assert that Fat files have no holes.
> -            //
> -
> -            ASSERT( Lbo != 0 );
> -
> -            //
> -            //  Write FAT_CLUSTER_AVAILABLE to each cluster in the run.
> -            //
> -
> -            ClusterCount = ByteCount >> LogOfBytesPerCluster;
> -            ClusterIndex = FatGetIndexFromLbo( Vcb, Lbo );
> -
> -            FatFreeClusters( IrpContext, Vcb, ClusterIndex, ClusterCount
> );
> -        }
> -
> -        //
> -        //  From now on, nothing can go wrong .... (as in raise)
> -        //
> -
> -        FatLockFreeClusterBitMap( Vcb );
> -
> -        for ( McbIndex = 0; McbIndex < RunsInMcb; McbIndex++ ) {
> -
> -            ULONG ClusterEnd;
> -            ULONG MyStart, MyLength, count;
> -#if DBG
> -#ifndef __REACTOS__
> -            ULONG PreviousClear, i;
> -#else
> -            ULONG i;
> -#endif
> -#endif
> -
> -            FatGetNextMcbEntry( Vcb, Mcb, McbIndex, &Vbo, &Lbo,
> &ByteCount );
> -
> -            //
> -            //  Mark the bits clear in the FreeClusterBitMap.
> -            //
> -
> -            ClusterCount = ByteCount >> LogOfBytesPerCluster;
> -            ClusterIndex = FatGetIndexFromLbo( Vcb, Lbo );
> -
> -            Window = Vcb->CurrentWindow;
> -
> -            //
> -            //  If we've divided the bitmap, elide bitmap manipulation for
> -            //  runs that are outside the current bucket.
> -            //
> -
> -            ClusterEnd = ClusterIndex + ClusterCount - 1;
> -
> -            if (!(ClusterIndex > Window->LastCluster ||
> -                  ClusterEnd  < Window->FirstCluster)) {
> -
> -                //
> -                //  The run being freed overlaps the current bucket, so
> we'll
> -                //  have to clear some bits.
> -                //
> -
> -                if (ClusterIndex < Window->FirstCluster &&
> -                    ClusterEnd > Window->LastCluster) {
> -
> -                    MyStart = Window->FirstCluster;
> -                    MyLength = Window->LastCluster - Window->FirstCluster
> + 1;
> -
> -                } else if (ClusterIndex < Window->FirstCluster) {
> -
> -                    MyStart = Window->FirstCluster;
> -                    MyLength = ClusterEnd - Window->FirstCluster + 1;
> -
> -                } else {
> -
> -                    //
> -                    //  The range being freed starts in the bucket, and
> may possibly
> -                    //  extend beyond the bucket.
> -                    //
> -
> -                    MyStart = ClusterIndex;
> -
> -                    if (ClusterEnd <= Window->LastCluster) {
> -
> -                        MyLength = ClusterCount;
> -
> -                    } else {
> -
> -                        MyLength = Window->LastCluster - ClusterIndex + 1;
> -                    }
> -                }
> -
> -                if (MyLength == 0) {
> -
> -                    continue;
> -                }
> -
> -#if DBG
> -#ifndef __REACTOS__
> -                PreviousClear = RtlNumberOfClearBits(
> &Vcb->FreeClusterBitMap );
> -#endif
> -
> -
> -                //
> -                //  Verify that the Bits are all really set.
> -                //
> -
> -                ASSERT( MyStart + MyLength - Window->FirstCluster <=
> Vcb->FreeClusterBitMap.SizeOfBitMap );
> -
> -                for (i = 0; i < MyLength; i++) {
> -
> -                    ASSERT( RtlCheckBit(&Vcb->FreeClusterBitMap,
> -                            MyStart - Window->FirstCluster + i) == 1 );
> -                }
> -#endif // DBG
> -
> -                FatUnreserveClusters( IrpContext, Vcb,
> -                                      MyStart - Window->FirstCluster + 2,
> -                                      MyLength );
> -            }
> -
> -            //
> -            //  Adjust the ClustersFree count for each bitmap window,
> even the ones
> -            //  that are not the current window.
> -            //
> -
> -            if (FatIsFat32(Vcb)) {
> -
> -                Window = &Vcb->Windows[FatWindowOfCluster( ClusterIndex
> )];
> -
> -            } else {
> -
> -                Window = &Vcb->Windows[0];
> -            }
> -
> -            MyStart = ClusterIndex;
> -
> -            for (MyLength = ClusterCount; MyLength > 0; MyLength -=
> count) {
> -
> -                count = FatMin(Window->LastCluster - MyStart + 1,
> MyLength);
> -                Window->ClustersFree += count;
> -
> -                //
> -                //  If this was not the last window this allocation
> spanned,
> -                //  advance to the next.
> -                //
> -
> -                if (MyLength != count) {
> -
> -                    Window++;
> -                    MyStart = Window->FirstCluster;
> -                }
> -            }
> -
> -            //
> -            //  Deallocation is now complete.  Adjust the free cluster
> count.
> -            //
> -
> -            Vcb->AllocationSupport.NumberOfFreeClusters += ClusterCount;
> -        }
> -
> -#if DBG
> -        if (Vcb->CurrentWindow->ClustersFree !=
> -               RtlNumberOfClearBits(&Vcb->FreeClusterBitMap)) {
> -
> -            DbgPrint("%x vs %x\n",  Vcb->CurrentWindow->ClustersFree,
> -                RtlNumberOfClearBits(&Vcb->FreeClusterBitMap));
> -
> -            DbgPrint("%x for %x\n", ClusterIndex, ClusterCount);
> -        }
> -#endif
> -
> -        FatUnlockFreeClusterBitMap( Vcb );
> -
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatDeallocateDiskSpace );
> -
> -        //
> -        //  Is there any unwinding to do?
> -        //
> -
> -        ExReleaseResourceLite(&Vcb->ChangeBitMapResource);
> -
> -        if ( _SEH2_AbnormalTermination() ) {
> -
> -            LBO Lbo;
> -            VBO Vbo;
> -
> -            ULONG Index;
> -            ULONG Clusters;
> -            ULONG FatIndex;
> -            ULONG PriorLastIndex;
> -
> -            //
> -            //  For each entry we already deallocated, reallocate it,
> -            //  chaining together as nessecary.  Note that we continue
> -            //  up to and including the last "for" iteration even though
> -            //  the SetFatRun could not have been successful.  This
> -            //  allows us a convienent way to re-link the final successful
> -            //  SetFatRun.
> -            //
> -            //  It is possible that the reason we got here will prevent us
> -            //  from succeeding in this operation.
> -            //
> -
> -            PriorLastIndex = 0;
> -
> -            for (Index = 0; Index <= McbIndex; Index++) {
> -
> -                FatGetNextMcbEntry(Vcb, Mcb, Index, &Vbo, &Lbo,
> &ByteCount);
> -
> -                FatIndex = FatGetIndexFromLbo( Vcb, Lbo );
> -                Clusters = ByteCount >> LogOfBytesPerCluster;
> -
> -                //
> -                //  We must always restore the prior iteration's last
> -                //  entry, pointing it to the first cluster of this run.
> -                //
> -
> -                if (PriorLastIndex != 0) {
> -
> -                    FatSetFatEntry( IrpContext,
> -                                    Vcb,
> -                                    PriorLastIndex,
> -                                    (FAT_ENTRY)FatIndex );
> -                }
> -
> -                //
> -                //  If this is not the last entry (the one that failed)
> -                //  then reallocate the disk space on the fat.
> -                //
> -
> -                if ( Index < McbIndex ) {
> -
> -                    FatAllocateClusters(IrpContext, Vcb, FatIndex,
> Clusters);
> -
> -                    PriorLastIndex = FatIndex + Clusters - 1;
> -                }
> -            }
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatDeallocateDiskSpace -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatSplitAllocation (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN OUT PLARGE_MCB Mcb,
> -    IN VBO SplitAtVbo,
> -    OUT PLARGE_MCB RemainingMcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This procedure takes a single mcb and splits its allocation into
> -    two separate allocation units.  The separation must only be done
> -    on cluster boundaries, otherwise we bugcheck.
> -
> -    On the disk this actually works by inserting a FAT_CLUSTER_LAST into
> -    the last index of the first part being split out.
> -
> -    Pictorially what is done is the following (where ! denotes the end of
> -    the fat chain (i.e., FAT_CLUSTER_LAST)):
> -
> -
> -        Mcb          |--a--|--b--|--c--|--d--|--e--|--f--|
> -
> -                                        ^
> -        SplitAtVbo ---------------------+
> -
> -        RemainingMcb (empty)
> -
> -    becomes
> -
> -        Mcb          |--a--|--b--|--c--!
> -
> -
> -        RemainingMcb |--d--|--e--|--f--|
> -
> -Arguments:
> -
> -    Vcb - Supplies the VCB being modified
> -
> -    Mcb - Supplies the MCB describing the allocation being split into
> -          two parts.  Upon return this Mcb now contains the first chain.
> -
> -    SplitAtVbo - Supplies the VBO of the first byte for the second chain
> -                 that we creating.
> -
> -    RemainingMcb - Receives the MCB describing the second chain of
> allocated
> -                   disk space.  The caller passes in an initialized Mcb
> that
> -                   is filled in by this procedure STARTING AT VBO 0.
> -
> -Return Value:
> -
> -    VOID - TRUE if the operation completed and FALSE if it had to
> -               block but could not.
> -
> ---*/
> -
> -{
> -    VBO SourceVbo;
> -    VBO TargetVbo;
> -    VBO DontCare;
> -
> -    LBO Lbo;
> -
> -    ULONG ByteCount;
> -    ULONG BytesPerCluster;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatSplitAllocation\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb          = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  Mcb          = %8lx\n", Mcb);
> -    DebugTrace( 0, Dbg, "  SplitAtVbo   = %8lx\n", SplitAtVbo);
> -    DebugTrace( 0, Dbg, "  RemainingMcb = %8lx\n", RemainingMcb);
> -
> -    BytesPerCluster = 1 << Vcb->AllocationSupport.LogOfBytesPerCluster;
> -
> -    //
> -    //  Assert that the split point is cluster alligned
> -    //
> -
> -    ASSERT( (SplitAtVbo & (BytesPerCluster - 1)) == 0 );
> -
> -    //
> -    //  We should never be handed an empty source MCB and asked to split
> -    //  at a non zero point.
> -    //
> -
> -    ASSERT( !((0 != SplitAtVbo) && (0 == FsRtlNumberOfRunsInLargeMcb(
> Mcb))));
> -
> -    //
> -    //  Assert we were given an empty target Mcb.
> -    //
> -
> -    //
> -    //  This assert is commented out to avoid hitting in the Ea error
> -    //  path.  In that case we will be using the same Mcb's to split the
> -    //  allocation that we used to merge them.  The target Mcb will
> contain
> -    //  the runs that the split will attempt to insert.
> -    //
> -    //
> -    //  ASSERT( FsRtlNumberOfRunsInMcb( RemainingMcb ) == 0 );
> -    //
> -
> -    _SEH2_TRY {
> -
> -        //
> -        //  Move the runs after SplitAtVbo from the souce to the target
> -        //
> -
> -        SourceVbo = SplitAtVbo;
> -        TargetVbo = 0;
> -
> -        while (FatLookupMcbEntry(Vcb, Mcb, SourceVbo, &Lbo, &ByteCount,
> NULL)) {
> -
> -            FatAddMcbEntry( Vcb, RemainingMcb, TargetVbo, Lbo, ByteCount
> );
> -
> -            FatRemoveMcbEntry( Vcb, Mcb, SourceVbo, ByteCount );
> -
> -            TargetVbo += ByteCount;
> -            SourceVbo += ByteCount;
> -
> -            //
> -            //  If SourceVbo overflows, we were actually snipping off the
> end
> -            //  of the maximal file ... and are now done.
> -            //
> -
> -            if (SourceVbo == 0) {
> -
> -                break;
> -            }
> -        }
> -
> -        //
> -        //  Mark the last pre-split cluster as a FAT_LAST_CLUSTER
> -        //
> -
> -        if ( SplitAtVbo != 0 ) {
> -
> -            FatLookupLastMcbEntry( Vcb, Mcb, &DontCare, &Lbo, NULL );
> -
> -            FatSetFatEntry( IrpContext,
> -                            Vcb,
> -                            FatGetIndexFromLbo( Vcb, Lbo ),
> -                            FAT_CLUSTER_LAST );
> -        }
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatSplitAllocation );
> -
> -        //
> -        //  If we got an exception, we must glue back together the Mcbs
> -        //
> -
> -        if ( _SEH2_AbnormalTermination() ) {
> -
> -            TargetVbo = SplitAtVbo;
> -            SourceVbo = 0;
> -
> -            while (FatLookupMcbEntry(Vcb, RemainingMcb, SourceVbo, &Lbo,
> &ByteCount, NULL)) {
> -
> -                FatAddMcbEntry( Vcb, Mcb, TargetVbo, Lbo, ByteCount );
> -
> -                FatRemoveMcbEntry( Vcb, RemainingMcb, SourceVbo,
> ByteCount );
> -
> -                TargetVbo += ByteCount;
> -                SourceVbo += ByteCount;
> -            }
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatSplitAllocation -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -VOID
> -FatMergeAllocation (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN OUT PLARGE_MCB Mcb,
> -    IN PLARGE_MCB SecondMcb
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine takes two separate allocations described by two MCBs and
> -    joins them together into one allocation.
> -
> -    Pictorially what is done is the following (where ! denotes the end of
> -    the fat chain (i.e., FAT_CLUSTER_LAST)):
> -
> -
> -        Mcb       |--a--|--b--|--c--!
> -
> -        SecondMcb |--d--|--e--|--f--|
> -
> -    becomes
> -
> -        Mcb       |--a--|--b--|--c--|--d--|--e--|--f--|
> -
> -        SecondMcb |--d--|--e--|--f--|
> -
> -
> -Arguments:
> -
> -    Vcb - Supplies the VCB being modified
> -
> -    Mcb - Supplies the MCB of the first allocation that is being modified.
> -          Upon return this Mcb will also describe the newly enlarged
> -          allocation
> -
> -    SecondMcb - Supplies the ZERO VBO BASED MCB of the second allocation
> -                that is being appended to the first allocation.  This
> -                procedure leaves SecondMcb unchanged.
> -
> -Return Value:
> -
> -    VOID - TRUE if the operation completed and FALSE if it had to
> -        block but could not.
> -
> ---*/
> -
> -{
> -    VBO SpliceVbo;
> -    LBO SpliceLbo;
> -
> -    VBO SourceVbo;
> -    VBO TargetVbo;
> -
> -    LBO Lbo;
> -
> -    ULONG ByteCount;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatMergeAllocation\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb       = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  Mcb       = %8lx\n", Mcb);
> -    DebugTrace( 0, Dbg, "  SecondMcb = %8lx\n", SecondMcb);
> -
> -    _SEH2_TRY {
> -
> -        //
> -        //  Append the runs from SecondMcb to Mcb
> -        //
> -
> -        (void)FatLookupLastMcbEntry( Vcb, Mcb, &SpliceVbo, &SpliceLbo,
> NULL );
> -
> -        SourceVbo = 0;
> -        TargetVbo = SpliceVbo + 1;
> -
> -        while (FatLookupMcbEntry(Vcb, SecondMcb, SourceVbo, &Lbo,
> &ByteCount, NULL)) {
> -
> -            FatAddMcbEntry( Vcb, Mcb, TargetVbo, Lbo, ByteCount );
> -
> -            SourceVbo += ByteCount;
> -            TargetVbo += ByteCount;
> -        }
> -
> -        //
> -        //  Link the last pre-merge cluster to the first cluster of
> SecondMcb
> -        //
> -
> -        FatLookupMcbEntry( Vcb, SecondMcb, 0, &Lbo, (PULONG)NULL, NULL );
> -
> -        FatSetFatEntry( IrpContext,
> -                        Vcb,
> -                        FatGetIndexFromLbo( Vcb, SpliceLbo ),
> -                        (FAT_ENTRY)FatGetIndexFromLbo( Vcb, Lbo ) );
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatMergeAllocation );
> -
> -        //
> -        //  If we got an exception, we must remove the runs added to Mcb
> -        //
> -
> -        if ( _SEH2_AbnormalTermination() ) {
> -
> -            ULONG CutLength;
> -
> -            if ((CutLength = TargetVbo - (SpliceVbo + 1)) != 0) {
> -
> -                FatRemoveMcbEntry( Vcb, Mcb, SpliceVbo + 1, CutLength);
> -            }
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatMergeAllocation -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -//
> -//  Internal support routine
> -//
> -
> -CLUSTER_TYPE
> -FatInterpretClusterType (
> -    IN PVCB Vcb,
> -    IN FAT_ENTRY Entry
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This procedure tells the caller how to interpret the input fat table
> -    entry.  It will indicate if the fat cluster is available, resereved,
> -    bad, the last one, or the another fat index.  This procedure can deal
> -    with both 12 and 16 bit fat.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to examine, yields 12/16 bit info
> -
> -    Entry - Supplies the fat entry to examine
> -
> -Return Value:
> -
> -    CLUSTER_TYPE - Is the type of the input Fat entry
> -
> ---*/
> -
> -{
> -    DebugTrace(+1, Dbg, "InterpretClusterType\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb   = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  Entry = %8lx\n", Entry);
> -
> -    PAGED_CODE();
> -
> -    switch(Vcb->AllocationSupport.FatIndexBitSize ) {
> -    case 32:
> -        Entry &= FAT32_ENTRY_MASK;
> -        break;
> -
> -    case 12:
> -        ASSERT( Entry <= 0xfff );
> -        if (Entry >= 0x0ff0) {
> -            Entry |= 0x0FFFF000;
> -        }
> -        break;
> -
> -    default:
> -    case 16:
> -        ASSERT( Entry <= 0xffff );
> -        if (Entry >= 0x0fff0) {
> -            Entry |= 0x0FFF0000;
> -        }
> -        break;
> -    }
> -
> -    if (Entry == FAT_CLUSTER_AVAILABLE) {
> -
> -        DebugTrace(-1, Dbg, "FatInterpretClusterType ->
> FatClusterAvailable\n", 0);
> -
> -        return FatClusterAvailable;
> -
> -    } else if (Entry < FAT_CLUSTER_RESERVED) {
> -
> -        DebugTrace(-1, Dbg, "FatInterpretClusterType ->
> FatClusterNext\n", 0);
> -
> -        return FatClusterNext;
> -
> -    } else if (Entry < FAT_CLUSTER_BAD) {
> -
> -        DebugTrace(-1, Dbg, "FatInterpretClusterType ->
> FatClusterReserved\n", 0);
> -
> -        return FatClusterReserved;
> -
> -    } else if (Entry == FAT_CLUSTER_BAD) {
> -
> -        DebugTrace(-1, Dbg, "FatInterpretClusterType -> FatClusterBad\n",
> 0);
> -
> -        return FatClusterBad;
> -
> -    } else {
> -
> -        DebugTrace(-1, Dbg, "FatInterpretClusterType ->
> FatClusterLast\n", 0);
> -
> -        return FatClusterLast;
> -    }
> -}
> -
> -
> -//
> -//  Internal support routine
> -//
> -
> -VOID
> -FatLookupFatEntry (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG FatIndex,
> -    IN OUT PULONG FatEntry,
> -    IN OUT PFAT_ENUMERATION_CONTEXT Context
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine takes an index into the fat and gives back the value
> -    in the Fat at this index.  At any given time, for a 16 bit fat, this
> -    routine allows only one page per volume of the fat to be pinned in
> -    memory.  For a 12 bit bit fat, the entire fat (max 6k) is pinned.
> This
> -    extra layer of caching makes the vast majority of requests very
> -    fast.  The context for this caching stored in a structure in the Vcb.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to examine, yields 12/16 bit info,
> -          fat access context, etc.
> -
> -    FatIndex - Supplies the fat index to examine.
> -
> -    FatEntry - Receives the fat entry pointed to by FatIndex.  Note that
> -               it must point to non-paged pool.
> -
> -    Context - This structure keeps track of a page of pinned fat between
> calls.
> -
> ---*/
> -
> -{
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatLookupFatEntry\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb      = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  FatIndex = %4x\n", FatIndex);
> -    DebugTrace( 0, Dbg, "  FatEntry = %8lx\n", FatEntry);
> -
> -    //
> -    //  Make sure they gave us a valid fat index.
> -    //
> -
> -    FatVerifyIndexIsValid(IrpContext, Vcb, FatIndex);
> -
> -    //
> -    //  Case on 12 or 16 bit fats.
> -    //
> -    //  In the 12 bit case (mostly floppies) we always have the whole fat
> -    //  (max 6k bytes) pinned during allocation operations.  This is
> possibly
> -    //  a wee bit slower, but saves headaches over fat entries with 8 bits
> -    //  on one page, and 4 bits on the next.
> -    //
> -    //  The 16 bit case always keeps the last used page pinned until all
> -    //  operations are done and it is unpinned.
> -    //
> -
> -    //
> -    //  DEAL WITH 12 BIT CASE
> -    //
> -
> -    if (Vcb->AllocationSupport.FatIndexBitSize == 12) {
> -
> -        //
> -        //  Check to see if the fat is already pinned, otherwise pin it.
> -        //
> -
> -        if (Context->Bcb == NULL) {
> -
> -            FatReadVolumeFile( IrpContext,
> -                               Vcb,
> -                               FatReservedBytes( &Vcb->Bpb ),
> -                               FatBytesPerFat( &Vcb->Bpb ),
> -                               &Context->Bcb,
> -                               &Context->PinnedPage );
> -        }
> -
> -        //
> -        //  Load the return value.
> -        //
> -
> -
> -        FatLookup12BitEntry( Context->PinnedPage, FatIndex, FatEntry );
> -
> -    } else if (Vcb->AllocationSupport.FatIndexBitSize == 32) {
> -
> -        //
> -        //  DEAL WITH 32 BIT CASE
> -        //
> -
> -        ULONG PageEntryOffset;
> -        ULONG OffsetIntoVolumeFile;
> -
> -        //
> -        //  Initialize two local variables that help us.
> -        //
> -        OffsetIntoVolumeFile = FatReservedBytes(&Vcb->Bpb) + FatIndex *
> sizeof(FAT_ENTRY);
> -        PageEntryOffset = (OffsetIntoVolumeFile % PAGE_SIZE) /
> sizeof(FAT_ENTRY);
> -
> -        //
> -        //  Check to see if we need to read in a new page of fat
> -        //
> -
> -        if ((Context->Bcb == NULL) ||
> -            (OffsetIntoVolumeFile / PAGE_SIZE != Context->VboOfPinnedPage
> / PAGE_SIZE)) {
> -
> -            //
> -            //  The entry wasn't in the pinned page, so must we unpin the
> current
> -            //  page (if any) and read in a new page.
> -            //
> -
> -            FatUnpinBcb( IrpContext, Context->Bcb );
> -
> -            FatReadVolumeFile( IrpContext,
> -                               Vcb,
> -                               OffsetIntoVolumeFile & ~(PAGE_SIZE - 1),
> -                               PAGE_SIZE,
> -                               &Context->Bcb,
> -                               &Context->PinnedPage );
> -
> -            Context->VboOfPinnedPage = OffsetIntoVolumeFile & ~(PAGE_SIZE
> - 1);
> -        }
> -
> -        //
> -        //  Grab the fat entry from the pinned page, and return
> -        //
> -
> -        *FatEntry = ((PULONG)(Context->PinnedPage))[PageEntryOffset] &
> FAT32_ENTRY_MASK;
> -
> -    } else {
> -
> -        //
> -        //  DEAL WITH 16 BIT CASE
> -        //
> -
> -        ULONG PageEntryOffset;
> -        ULONG OffsetIntoVolumeFile;
> -
> -        //
> -        //  Initialize two local variables that help us.
> -        //
> -
> -        OffsetIntoVolumeFile = FatReservedBytes(&Vcb->Bpb) + FatIndex *
> sizeof(USHORT);
> -        PageEntryOffset = (OffsetIntoVolumeFile % PAGE_SIZE) /
> sizeof(USHORT);
> -
> -        //
> -        //  Check to see if we need to read in a new page of fat
> -        //
> -
> -        if ((Context->Bcb == NULL) ||
> -            (OffsetIntoVolumeFile / PAGE_SIZE != Context->VboOfPinnedPage
> / PAGE_SIZE)) {
> -
> -            //
> -            //  The entry wasn't in the pinned page, so must we unpin the
> current
> -            //  page (if any) and read in a new page.
> -            //
> -
> -            FatUnpinBcb( IrpContext, Context->Bcb );
> -
> -            FatReadVolumeFile( IrpContext,
> -                               Vcb,
> -                               OffsetIntoVolumeFile & ~(PAGE_SIZE - 1),
> -                               PAGE_SIZE,
> -                               &Context->Bcb,
> -                               &Context->PinnedPage );
> -
> -            Context->VboOfPinnedPage = OffsetIntoVolumeFile & ~(PAGE_SIZE
> - 1);
> -        }
> -
> -        //
> -        //  Grab the fat entry from the pinned page, and return
> -        //
> -
> -        *FatEntry = ((PUSHORT)(Context->PinnedPage))[PageEntryOffset];
> -    }
> -
> -    DebugTrace(-1, Dbg, "FatLookupFatEntry -> (VOID)\n", 0);
> -    return;
> -}
> -
> -
> -VOID
> -FatSetFatEntry (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG FatIndex,
> -    IN FAT_ENTRY FatEntry
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine takes an index into the fat and puts a value in the Fat
> -    at this index.  The routine special cases 12, 16 and 32 bit fats.  In
> -    all cases we go to the cache manager for a piece of the fat.
> -
> -    We have a special form of this call for setting the DOS-style dirty
> bit.
> -    Unlike the dirty bit in the boot sector, we do not go to special
> effort
> -    to make sure that this hits the disk synchronously - if the system
> goes
> -    down in the window between the dirty bit being set in the boot sector
> -    and the FAT index zero dirty bit being lazy written, then life is
> tough.
> -
> -    The only possible scenario is that Win9x may see what it thinks is a
> clean
> -    volume that really isn't (hopefully Memphis will pay attention to our
> dirty
> -    bit as well). The dirty bit will get out quickly, and if heavy
> activity is
> -    occurring, then the dirty bit should actually be there virtually all
> of the
> -    time since the act of cleaning the volume is the "rare" occurance.
> -
> -    There are synchronization concerns that would crop up if we tried to
> make
> -    this synchronous. This thread may already own the Bcb shared for the
> first
> -    sector of the FAT (so we can't get it exclusive for a writethrough).
> This
> -    would require some more serious replumbing to work around than I want
> to
> -    consider at this time.
> -
> -    We can and do, however, synchronously set the bit clean.
> -
> -    At this point the reader should understand why the NT dirty bit is
> where it is.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to examine, yields 12/16/32 bit info, etc.
> -
> -    FatIndex - Supplies the destination fat index.
> -
> -    FatEntry - Supplies the source fat entry.
> -
> ---*/
> -
> -{
> -    LBO Lbo;
> -    PBCB Bcb = NULL;
> -    ULONG SectorSize;
> -    ULONG OffsetIntoVolumeFile;
> -    ULONG WasWait = TRUE;
> -    BOOLEAN RegularOperation = TRUE;
> -    BOOLEAN CleaningOperation = FALSE;
> -    BOOLEAN ReleaseMutex = FALSE;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatSetFatEntry\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb      = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  FatIndex = %4x\n", FatIndex);
> -    DebugTrace( 0, Dbg, "  FatEntry = %4x\n", FatEntry);
> -
> -    //
> -    //  Make sure they gave us a valid fat index if this isn't the special
> -    //  clean-bit modifying call.
> -    //
> -
> -    if (FatIndex == FAT_DIRTY_BIT_INDEX) {
> -
> -        //
> -        //  We are setting the clean bit state.  Of course, we could
> -        //  have corruption that would cause us to try to fiddle the
> -        //  reserved index - we guard against this by having the
> -        //  special entry values use the reserved high 4 bits that
> -        //  we know that we'll never try to set.
> -        //
> -
> -        //
> -        //  We don't want to repin the FAT pages involved here.  Just
> -        //  let the lazy writer hit them when it can.
> -        //
> -
> -        RegularOperation = FALSE;
> -
> -        switch (FatEntry) {
> -            case FAT_CLEAN_VOLUME:
> -                FatEntry = FAT_CLEAN_ENTRY;
> -                CleaningOperation = TRUE;
> -                break;
> -
> -            case FAT_DIRTY_VOLUME:
> -                switch (Vcb->AllocationSupport.FatIndexBitSize) {
> -                    case 12:
> -                        FatEntry = FAT12_DIRTY_ENTRY;
> -                        break;
> -
> -                    case 32:
> -                        FatEntry = FAT32_DIRTY_ENTRY;
> -                        break;
> -
> -                    default:
> -                        FatEntry = FAT16_DIRTY_ENTRY;
> -                        break;
> -                }
> -                break;
> -
> -            default:
> -                FatRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
> -                break;
> -        }
> -
> -        //
> -        //  Disable dirtying semantics for the duration of this
> operation.  Force this
> -        //  operation to wait for the duration.
> -        //
> -
> -        WasWait = FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
> -        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT |
> IRP_CONTEXT_FLAG_DISABLE_DIRTY );
> -
> -    } else {
> -
> -        ASSERT( !(FatEntry & ~FAT32_ENTRY_MASK) );
> -        FatVerifyIndexIsValid(IrpContext, Vcb, FatIndex);
> -    }
> -
> -    //
> -    //  Set Sector Size
> -    //
> -
> -    SectorSize = 1 << Vcb->AllocationSupport.LogOfBytesPerSector;
> -
> -    //
> -    //  Case on 12 or 16 bit fats.
> -    //
> -    //  In the 12 bit case (mostly floppies) we always have the whole fat
> -    //  (max 6k bytes) pinned during allocation operations.  This is
> possibly
> -    //  a wee bit slower, but saves headaches over fat entries with 8 bits
> -    //  on one page, and 4 bits on the next.
> -    //
> -    //  In the 16 bit case we only read the page that we need to set the
> fat
> -    //  entry.
> -    //
> -
> -    //
> -    //  DEAL WITH 12 BIT CASE
> -    //
> -
> -    _SEH2_TRY {
> -
> -        if (Vcb->AllocationSupport.FatIndexBitSize == 12) {
> -
> -            PVOID PinnedFat;
> -
> -            //
> -            //  Make sure we have a valid entry
> -            //
> -
> -            FatEntry &= 0xfff;
> -
> -            //
> -            //  We read in the entire fat.  Note that using prepare write
> marks
> -            //  the bcb pre-dirty, so we don't have to do it explicitly.
> -            //
> -
> -            OffsetIntoVolumeFile = FatReservedBytes( &Vcb->Bpb ) +
> FatIndex * 3 / 2;
> -
> -            FatPrepareWriteVolumeFile( IrpContext,
> -                                       Vcb,
> -                                       FatReservedBytes( &Vcb->Bpb ),
> -                                       FatBytesPerFat( &Vcb->Bpb ),
> -                                       &Bcb,
> -                                       &PinnedFat,
> -                                       RegularOperation,
> -                                       FALSE );
> -
> -            //
> -            //  Mark the sector(s) dirty in the DirtyFatMcb.  This call is
> -            //  complicated somewhat for the 12 bit case since a single
> -            //  entry write can span two sectors (and pages).
> -            //
> -            //  Get the Lbo for the sector where the entry starts, and
> add it to
> -            //  the dirty fat Mcb.
> -            //
> -
> -            Lbo = OffsetIntoVolumeFile & ~(SectorSize - 1);
> -
> -            FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize);
> -
> -            //
> -            //  If the entry started on the last byte of the sector, it
> continues
> -            //  to the next sector, so mark the next sector dirty as well.
> -            //
> -            //  Note that this entry will simply coalese with the last
> entry,
> -            //  so this operation cannot fail.  Also if we get this far,
> we have
> -            //  made it, so no unwinding will be needed.
> -            //
> -
> -            if ( (OffsetIntoVolumeFile & (SectorSize - 1)) == (SectorSize
> - 1) ) {
> -
> -                Lbo += SectorSize;
> -
> -                FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize );
> -            }
> -
> -            //
> -            //  Store the entry into the fat; we need a little
> synchonization
> -            //  here and can't use a spinlock since the bytes might not be
> -            //  resident.
> -            //
> -
> -            FatLockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = TRUE;
> -
> -            FatSet12BitEntry( PinnedFat, FatIndex, FatEntry );
> -
> -            FatUnlockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = FALSE;
> -
> -        } else if (Vcb->AllocationSupport.FatIndexBitSize == 32) {
> -
> -            //
> -            //  DEAL WITH 32 BIT CASE
> -            //
> -
> -            PULONG PinnedFatEntry32;
> -
> -            //
> -            //  Read in a new page of fat
> -            //
> -
> -            OffsetIntoVolumeFile = FatReservedBytes( &Vcb->Bpb ) +
> -                                   FatIndex * sizeof( FAT_ENTRY );
> -
> -            FatPrepareWriteVolumeFile( IrpContext,
> -                                       Vcb,
> -                                       OffsetIntoVolumeFile,
> -                                       sizeof(FAT_ENTRY),
> -                                       &Bcb,
> -                                       (PVOID *)&PinnedFatEntry32,
> -                                       RegularOperation,
> -                                       FALSE );
> -            //
> -            //  Mark the sector dirty in the DirtyFatMcb
> -            //
> -
> -            Lbo = OffsetIntoVolumeFile & ~(SectorSize - 1);
> -
> -            FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize);
> -
> -            //
> -            //  Store the FatEntry to the pinned page.
> -            //
> -            //  Preserve the reserved bits in FAT32 entries in the file
> heap.
> -            //
> -
> -#ifdef ALPHA
> -            FatLockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = TRUE;
> -#endif // ALPHA
> -
> -            if (FatIndex != FAT_DIRTY_BIT_INDEX) {
> -
> -                *PinnedFatEntry32 = ((*PinnedFatEntry32 &
> ~FAT32_ENTRY_MASK) | FatEntry);
> -
> -            } else {
> -
> -                *PinnedFatEntry32 = FatEntry;
> -            }
> -
> -#ifdef ALPHA
> -            FatUnlockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = FALSE;
> -#endif // ALPHA
> -
> -        } else {
> -
> -            //
> -            //  DEAL WITH 16 BIT CASE
> -            //
> -
> -            PUSHORT PinnedFatEntry;
> -
> -            //
> -            //  Read in a new page of fat
> -            //
> -
> -            OffsetIntoVolumeFile = FatReservedBytes( &Vcb->Bpb ) +
> -                                   FatIndex * sizeof(USHORT);
> -
> -            FatPrepareWriteVolumeFile( IrpContext,
> -                                       Vcb,
> -                                       OffsetIntoVolumeFile,
> -                                       sizeof(USHORT),
> -                                       &Bcb,
> -                                       (PVOID *)&PinnedFatEntry,
> -                                       RegularOperation,
> -                                       FALSE );
> -            //
> -            //  Mark the sector dirty in the DirtyFatMcb
> -            //
> -
> -            Lbo = OffsetIntoVolumeFile & ~(SectorSize - 1);
> -
> -            FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize);
> -
> -            //
> -            //  Store the FatEntry to the pinned page.
> -            //
> -            //  We need extra synchronization here for broken
> architectures
> -            //  like the ALPHA that don't support atomic 16 bit writes.
> -            //
> -
> -#ifdef ALPHA
> -            FatLockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = TRUE;
> -#endif // ALPHA
> -
> -            *PinnedFatEntry = (USHORT)FatEntry;
> -
> -#ifdef ALPHA
> -            FatUnlockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = FALSE;
> -#endif // ALPHA
> -        }
> -
> -    } _SEH2_FINALLY {
> -
> -        DebugUnwind( FatSetFatEntry );
> -
> -        //
> -        //  Re-enable volume dirtying in case this was a dirty bit
> operation.
> -        //
> -
> -        ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_DIRTY );
> -
> -        //
> -        //  Make this operation asynchronous again if needed.
> -        //
> -
> -        if (!WasWait) {
> -
> -            ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
> -        }
> -
> -        //
> -        //  If we still somehow have the Mutex, release it.
> -        //
> -
> -        if (ReleaseMutex) {
> -
> -            ASSERT( _SEH2_AbnormalTermination() );
> -
> -            FatUnlockFreeClusterBitMap( Vcb );
> -        }
> -
> -        //
> -        //  Unpin the Bcb.  For cleaning operations, we make this
> write-through.
> -        //
> -
> -        if (CleaningOperation && Bcb) {
> -
> -            IO_STATUS_BLOCK IgnoreStatus;
> -
> -            CcRepinBcb( Bcb );
> -            CcUnpinData( Bcb );
> -            DbgDoit( IrpContext->PinCount -= 1 );
> -            CcUnpinRepinnedBcb( Bcb, TRUE, &IgnoreStatus );
> -
> -        } else {
> -
> -            FatUnpinBcb(IrpContext, Bcb);
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatSetFatEntry -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -//
> -//  Internal support routine
> -//
> -
> -VOID
> -FatSetFatRun (
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG StartingFatIndex,
> -    IN ULONG ClusterCount,
> -    IN BOOLEAN ChainTogether
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine sets a continuous run of clusters in the fat.  If
> ChainTogether
> -    is TRUE, then the clusters are linked together as in normal Fat
> fasion,
> -    with the last cluster receiving FAT_CLUSTER_LAST.  If ChainTogether is
> -    FALSE, all the entries are set to FAT_CLUSTER_AVAILABLE, effectively
> -    freeing all the clusters in the run.
> -
> -Arguments:
> -
> -    Vcb - Supplies the Vcb to examine, yields 12/16 bit info, etc.
> -
> -    StartingFatIndex - Supplies the destination fat index.
> -
> -    ClusterCount - Supplies the number of contiguous clusters to work on.
> -
> -    ChainTogether - Tells us whether to fill the entries with links, or
> -                    FAT_CLUSTER_AVAILABLE
> -
> -
> -Return Value:
> -
> -    VOID
> -
> ---*/
> -
> -{
> -#define MAXCOUNTCLUS 0x10000
> -#define COUNTSAVEDBCBS ((MAXCOUNTCLUS * sizeof(FAT_ENTRY) / PAGE_SIZE) +
> 2)
> -    PBCB SavedBcbs[COUNTSAVEDBCBS][2];
> -
> -    ULONG SectorSize;
> -    ULONG Cluster;
> -
> -    LBO StartSectorLbo;
> -    LBO FinalSectorLbo;
> -    LBO Lbo;
> -
> -    PVOID PinnedFat;
> -
> -#ifndef __REACTOS__
> -    ULONG StartingPage;
> -#endif
> -
> -    BOOLEAN ReleaseMutex = FALSE;
> -
> -    ULONG SavedStartingFatIndex = StartingFatIndex;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "FatSetFatRun\n", 0);
> -    DebugTrace( 0, Dbg, "  Vcb              = %8lx\n", Vcb);
> -    DebugTrace( 0, Dbg, "  StartingFatIndex = %8x\n", StartingFatIndex);
> -    DebugTrace( 0, Dbg, "  ClusterCount     = %8lx\n", ClusterCount);
> -    DebugTrace( 0, Dbg, "  ChainTogether    = %s\n", ChainTogether ?
> "TRUE":"FALSE");
> -
> -    //
> -    //  Make sure they gave us a valid fat run.
> -    //
> -
> -    FatVerifyIndexIsValid(IrpContext, Vcb, StartingFatIndex);
> -    FatVerifyIndexIsValid(IrpContext, Vcb, StartingFatIndex +
> ClusterCount - 1);
> -
> -    //
> -    //  Check special case
> -    //
> -
> -    if (ClusterCount == 0) {
> -
> -        DebugTrace(-1, Dbg, "FatSetFatRun -> (VOID)\n", 0);
> -        return;
> -    }
> -
> -    //
> -    //  Set Sector Size
> -    //
> -
> -    SectorSize = 1 << Vcb->AllocationSupport.LogOfBytesPerSector;
> -
> -    //
> -    //  Case on 12 or 16 bit fats.
> -    //
> -    //  In the 12 bit case (mostly floppies) we always have the whole fat
> -    //  (max 6k bytes) pinned during allocation operations.  This is
> possibly
> -    //  a wee bit slower, but saves headaches over fat entries with 8 bits
> -    //  on one page, and 4 bits on the next.
> -    //
> -    //  In the 16 bit case we only read one page at a time, as needed.
> -    //
> -
> -    //
> -    //  DEAL WITH 12 BIT CASE
> -    //
> -
> -    _SEH2_TRY {
> -
> -        if (Vcb->AllocationSupport.FatIndexBitSize == 12) {
> -
> -#ifndef __REACTOS__
> -            StartingPage = 0;
> -#endif
> -
> -            //
> -            //  We read in the entire fat.  Note that using prepare write
> marks
> -            //  the bcb pre-dirty, so we don't have to do it explicitly.
> -            //
> -
> -            RtlZeroMemory( &SavedBcbs[0], 2 * sizeof(PBCB) * 2);
> -
> -            FatPrepareWriteVolumeFile( IrpContext,
> -                                       Vcb,
> -                                       FatReservedBytes( &Vcb->Bpb ),
> -                                       FatBytesPerFat( &Vcb->Bpb ),
> -                                       &SavedBcbs[0][0],
> -                                       &PinnedFat,
> -                                       TRUE,
> -                                       FALSE );
> -
> -            //
> -            //  Mark the affected sectors dirty.  Note that
> FinalSectorLbo is
> -            //  the Lbo of the END of the entry (Thus * 3 + 2).  This
> makes sure
> -            //  we catch the case of a dirty fat entry straddling a
> sector boundry.
> -            //
> -            //  Note that if the first AddMcbEntry succeeds, all
> following ones
> -            //  will simply coalese, and thus also succeed.
> -            //
> -
> -            StartSectorLbo = (FatReservedBytes( &Vcb->Bpb ) +
> StartingFatIndex * 3 / 2)
> -                             & ~(SectorSize - 1);
> -
> -            FinalSectorLbo = (FatReservedBytes( &Vcb->Bpb ) +
> ((StartingFatIndex +
> -                             ClusterCount) * 3 + 2) / 2) & ~(SectorSize -
> 1);
> -
> -            for (Lbo = StartSectorLbo; Lbo <= FinalSectorLbo; Lbo +=
> SectorSize) {
> -
> -                FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize );
> -            }
> -
> -            //
> -            //  Store the entries into the fat; we need a little
> -            //  synchonization here and can't use a spinlock since the
> bytes
> -            //  might not be resident.
> -            //
> -
> -            FatLockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = TRUE;
> -
> -            for (Cluster = StartingFatIndex;
> -                 Cluster < StartingFatIndex + ClusterCount - 1;
> -                 Cluster++) {
> -
> -                FatSet12BitEntry( PinnedFat,
> -                                  Cluster,
> -                                  ChainTogether ? Cluster + 1 :
> FAT_CLUSTER_AVAILABLE );
> -            }
> -
> -            //
> -            //  Save the last entry
> -            //
> -
> -            FatSet12BitEntry( PinnedFat,
> -                              Cluster,
> -                              ChainTogether ?
> -                              FAT_CLUSTER_LAST & 0xfff :
> FAT_CLUSTER_AVAILABLE );
> -
> -            FatUnlockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = FALSE;
> -
> -        } else if (Vcb->AllocationSupport.FatIndexBitSize == 32) {
> -
> -            //
> -            //  DEAL WITH 32 BIT CASE
> -            //
> -
> -            for (;;) {
> -
> -                VBO StartOffsetInVolume;
> -                VBO FinalOffsetInVolume;
> -
> -                ULONG Page;
> -                ULONG FinalCluster;
> -                PULONG FatEntry;
> -                ULONG ClusterCountThisRun;
> -
> -                StartOffsetInVolume = FatReservedBytes(&Vcb->Bpb) +
> -                                            StartingFatIndex *
> sizeof(FAT_ENTRY);
> -
> -                if (ClusterCount > MAXCOUNTCLUS) {
> -                    ClusterCountThisRun = MAXCOUNTCLUS;
> -                } else {
> -                    ClusterCountThisRun = ClusterCount;
> -                }
> -
> -                FinalOffsetInVolume = StartOffsetInVolume +
> -                                            (ClusterCountThisRun -  1) *
> sizeof(FAT_ENTRY);
> -
> -#ifndef __REACTOS__
> -                StartingPage = StartOffsetInVolume / PAGE_SIZE;
> -#endif
> -
> -                {
> -                    ULONG NumberOfPages;
> -                    ULONG Offset;
> -
> -                    NumberOfPages = (FinalOffsetInVolume / PAGE_SIZE) -
> -                                    (StartOffsetInVolume / PAGE_SIZE) + 1;
> -
> -                    RtlZeroMemory( &SavedBcbs[0][0], (NumberOfPages + 1)
> * sizeof(PBCB) * 2 );
> -
> -                    for ( Page = 0, Offset = StartOffsetInVolume &
> ~(PAGE_SIZE - 1);
> -                          Page < NumberOfPages;
> -                          Page++, Offset += PAGE_SIZE ) {
> -
> -                        FatPrepareWriteVolumeFile( IrpContext,
> -                                                   Vcb,
> -                                                   Offset,
> -                                                   PAGE_SIZE,
> -                                                   &SavedBcbs[Page][0],
> -                                                   (PVOID
> *)&SavedBcbs[Page][1],
> -                                                   TRUE,
> -                                                   FALSE );
> -
> -                        if (Page == 0) {
> -
> -                            FatEntry = (PULONG)((PUCHAR)SavedBcbs[0][1] +
> -                                                (StartOffsetInVolume %
> PAGE_SIZE));
> -                        }
> -                    }
> -                }
> -
> -                //
> -                //  Mark the run dirty
> -                //
> -
> -                StartSectorLbo = StartOffsetInVolume & ~(SectorSize - 1);
> -                FinalSectorLbo = FinalOffsetInVolume & ~(SectorSize - 1);
> -
> -                for (Lbo = StartSectorLbo; Lbo <= FinalSectorLbo; Lbo +=
> SectorSize) {
> -
> -                    FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO)Lbo,
> Lbo, SectorSize );
> -                }
> -
> -                //
> -                //  Store the entries
> -                //
> -                //  We need extra synchronization here for broken
> architectures
> -                //  like the ALPHA that don't support atomic 16 bit
> writes.
> -                //
> -
> -#ifdef ALPHA
> -                FatLockFreeClusterBitMap( Vcb );
> -                ReleaseMutex = TRUE;
> -#endif // ALPHA
> -
> -                FinalCluster = StartingFatIndex + ClusterCountThisRun - 1;
> -                Page = 0;
> -
> -                for (Cluster = StartingFatIndex;
> -                     Cluster <= FinalCluster;
> -                     Cluster++, FatEntry++) {
> -
> -                    //
> -                    //  If we just crossed a page boundry (as opposed to
> starting
> -                    //  on one), update our idea of FatEntry.
> -
> -                    if ( (((ULONG_PTR)FatEntry & (PAGE_SIZE-1)) == 0) &&
> -                         (Cluster != StartingFatIndex) ) {
> -
> -                        Page += 1;
> -                        FatEntry = (PULONG)SavedBcbs[Page][1];
> -                    }
> -
> -                    *FatEntry = ChainTogether ? (FAT_ENTRY)(Cluster + 1) :
> -                                                FAT_CLUSTER_AVAILABLE;
> -                }
> -
> -                //
> -                //  Fix up the last entry if we were chaining together
> -                //
> -
> -                if ((ClusterCount <= MAXCOUNTCLUS) &&
> -                    ChainTogether ) {
> -
> -                    *(FatEntry-1) = FAT_CLUSTER_LAST;
> -                }
> -
> -#ifdef ALPHA
> -                FatUnlockFreeClusterBitMap( Vcb );
> -                ReleaseMutex = FALSE;
> -#endif // ALPHA
> -
> -                {
> -                    ULONG i = 0;
> -                    //
> -                    //  Unpin the Bcbs
> -                    //
> -
> -                    while ( SavedBcbs[i][0] != NULL ) {
> -
> -                        FatUnpinBcb( IrpContext, SavedBcbs[i][0] );
> -                        SavedBcbs[i][0] = NULL;
> -
> -                        i += 1;
> -                    }
> -                }
> -
> -                if (ClusterCount <= MAXCOUNTCLUS) {
> -
> -                    break;
> -
> -                } else {
> -
> -                    StartingFatIndex += MAXCOUNTCLUS;
> -                    ClusterCount -= MAXCOUNTCLUS;
> -                }
> -            }
> -
> -        } else {
> -
> -            //
> -            //  DEAL WITH 16 BIT CASE
> -            //
> -
> -            VBO StartOffsetInVolume;
> -            VBO FinalOffsetInVolume;
> -
> -            ULONG Page;
> -            ULONG FinalCluster;
> -            PUSHORT FatEntry;
> -
> -            StartOffsetInVolume = FatReservedBytes(&Vcb->Bpb) +
> -                                        StartingFatIndex * sizeof(USHORT);
> -
> -            FinalOffsetInVolume = StartOffsetInVolume +
> -                                        (ClusterCount - 1) *
> sizeof(USHORT);
> -
> -#ifndef __REACTOS__
> -            StartingPage = StartOffsetInVolume / PAGE_SIZE;
> -#endif
> -
> -            //
> -            //  Read in one page of fat at a time.  We cannot read in the
> -            //  all of the fat we need because of cache manager
> limitations.
> -            //
> -            //  SavedBcb was initialized to be able to hold the largest
> -            //  possible number of pages in a fat plus and extra one to
> -            //  accomadate the boot sector, plus one more to make sure
> there
> -            //  is enough room for the RtlZeroMemory below that needs the
> mark
> -            //  the first Bcb after all the ones we will use as an end
> marker.
> -            //
> -
> -            {
> -                ULONG NumberOfPages;
> -                ULONG Offset;
> -
> -                NumberOfPages = (FinalOffsetInVolume / PAGE_SIZE) -
> -                                (StartOffsetInVolume / PAGE_SIZE) + 1;
> -
> -                RtlZeroMemory( &SavedBcbs[0][0], (NumberOfPages + 1) *
> sizeof(PBCB) * 2 );
> -
> -                for ( Page = 0, Offset = StartOffsetInVolume &
> ~(PAGE_SIZE - 1);
> -                      Page < NumberOfPages;
> -                      Page++, Offset += PAGE_SIZE ) {
> -
> -                    FatPrepareWriteVolumeFile( IrpContext,
> -                                               Vcb,
> -                                               Offset,
> -                                               PAGE_SIZE,
> -                                               &SavedBcbs[Page][0],
> -                                               (PVOID
> *)&SavedBcbs[Page][1],
> -                                               TRUE,
> -                                               FALSE );
> -
> -                    if (Page == 0) {
> -
> -                        FatEntry = (PUSHORT)((PUCHAR)SavedBcbs[0][1] +
> -                                            (StartOffsetInVolume %
> PAGE_SIZE));
> -                    }
> -                }
> -            }
> -
> -            //
> -            //  Mark the run dirty
> -            //
> -
> -            StartSectorLbo = StartOffsetInVolume & ~(SectorSize - 1);
> -            FinalSectorLbo = FinalOffsetInVolume & ~(SectorSize - 1);
> -
> -            for (Lbo = StartSectorLbo; Lbo <= FinalSectorLbo; Lbo +=
> SectorSize) {
> -
> -                FatAddMcbEntry( Vcb, &Vcb->DirtyFatMcb, (VBO) Lbo, Lbo,
> SectorSize );
> -            }
> -
> -            //
> -            //  Store the entries
> -            //
> -            //  We need extra synchronization here for broken
> architectures
> -            //  like the ALPHA that don't support atomic 16 bit writes.
> -            //
> -
> -#ifdef ALPHA
> -            FatLockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = TRUE;
> -#endif // ALPHA
> -
> -            FinalCluster = StartingFatIndex + ClusterCount - 1;
> -            Page = 0;
> -
> -            for (Cluster = StartingFatIndex;
> -                 Cluster <= FinalCluster;
> -                 Cluster++, FatEntry++) {
> -
> -                //
> -                //  If we just crossed a page boundry (as opposed to
> starting
> -                //  on one), update our idea of FatEntry.
> -
> -                if ( (((ULONG_PTR)FatEntry & (PAGE_SIZE-1)) == 0) &&
> -                     (Cluster != StartingFatIndex) ) {
> -
> -                    Page += 1;
> -                    FatEntry = (PUSHORT)SavedBcbs[Page][1];
> -                }
> -
> -                *FatEntry = (USHORT) (ChainTogether ? (FAT_ENTRY)(Cluster
> + 1) :
> -
> FAT_CLUSTER_AVAILABLE);
> -            }
> -
> -            //
> -            //  Fix up the last entry if we were chaining together
> -            //
> -
> -            if ( ChainTogether ) {
> -
> -                *(FatEntry-1) = (USHORT)FAT_CLUSTER_LAST;
> -            }
> -#ifdef ALPHA
> -            FatUnlockFreeClusterBitMap( Vcb );
> -            ReleaseMutex = FALSE;
> -#endif // ALPHA
> -        }
> -
> -    } _SEH2_FINALLY {
> -
> -        ULONG i = 0;
> -
> -        DebugUnwind( FatSetFatRun );
> -
> -        //
> -        //  If we still somehow have the Mutex, release it.
> -        //
> -
> -        if (ReleaseMutex) {
> -
> -            ASSERT( _SEH2_AbnormalTermination() );
> -
> -            FatUnlockFreeClusterBitMap( Vcb );
> -        }
> -
> -        //
> -        //  Unpin the Bcbs
> -        //
> -
> -        while ( SavedBcbs[i][0] != NULL ) {
> -
> -            FatUnpinBcb( IrpContext, SavedBcbs[i][0] );
> -
> -            i += 1;
> -        }
> -
> -        //
> -        //  At this point nothing in this finally clause should have
> raised.
> -        //  So, now comes the unsafe (sigh) stuff.
> -        //
> -
> -        if ( _SEH2_AbnormalTermination() &&
> -            (Vcb->AllocationSupport.FatIndexBitSize == 32) ) {
> -
> -            //
> -            //  Fat32 unwind
> -            //
> -            //  This case is more complex because the FAT12 and FAT16
> cases
> -            //  pin all the needed FAT pages (128K max), after which it
> -            //  can't fail, before changing any FAT entries.  In the Fat32
> -            //  case, it may not be practical to pin all the needed FAT
> -            //  pages, because that could span many megabytes.  So Fat32
> -            //  attacks in chunks, and if a failure occurs once the first
> -            //  chunk has been updated, we have to back out the updates.
> -            //
> -            //  The unwind consists of walking back over each FAT entry we
> -            //  have changed, setting it back to the previous value.  Note
> -            //  that the previous value with either be
> FAT_CLUSTER_AVAILABLE
> -            //  (if ChainTogether==TRUE) or a simple link to the successor
> -            //  (if ChainTogether==FALSE).
> -            //
> -            //  We concede that any one of these calls could fail too; our
> -            //  objective is to make this case no more likely than the
> case
> -            //  for a file consisting of multiple disjoint runs.
> -            //
> -
> -            while ( StartingFatIndex > SavedStartingFatIndex ) {
> -
> -                StartingFatIndex--;
> -
> -                FatSetFatEntry( IrpContext, Vcb, StartingFatIndex,
> -                    ChainTogether ?
> -                        StartingFatIndex + 1 : FAT_CLUSTER_AVAILABLE );
> -            }
> -        }
> -
> -        DebugTrace(-1, Dbg, "FatSetFatRun -> (VOID)\n", 0);
> -    } _SEH2_END;
> -
> -    return;
> -}
> -
> -
> -//
> -//  Internal support routine
> -//
> -
> -UCHAR
> -FatLogOf (
> -    IN ULONG Value
> -    )
> -
> -/*++
> -
> -Routine Description:
> -
> -    This routine just computes the base 2 log of an integer.  It is only
> used
> -    on objects that are know to be powers of two.
> -
> -Arguments:
> -
> -    Value - The value to take the base 2 log of.
> -
> -Return Value:
> -
> -    UCHAR - The base 2 log of Value.
> -
> ---*/
> -
> -{
> -    UCHAR Log = 0;
> -
> -    PAGED_CODE();
> -
> -    DebugTrace(+1, Dbg, "LogOf\n", 0);
> -    DebugTrace( 0, Dbg, "  Value = %8lx\n", Value);
> -
> -    //
> -    //  Knock bits off until we we get a one at position 0
> -    //
> -
> -    while ( (Value & 0xfffffffe) != 0 ) {
> -
> -        Log++;
> -        Value >>= 1;
> -    }
> -
> -    //
> -    //  If there was more than one bit set, the file system messed up,
> -    //  Bug Check.
> -    //
> -
> -    if (Value != 0x1) {
> -
> -        DebugTrace( 0, Dbg, "Received non power of 2.\n", 0);
> -
> -        FatBugCheck( Value, Log, 0 );
> -    }
> -
> -    DebugTrace(-1, Dbg, "LogOf -> %8lx\n", Log);
> -
> -    return Log;
> -}
> -
> -
> -VOID
> -FatExamineFatEntries(
> -    IN PIRP_CONTEXT IrpContext,
> -    IN PVCB Vcb,
> -    IN ULONG StartIndex OPTIONAL,
> -    IN ULONG EndIndex OPTIONAL,
> -    IN BOOLEAN SetupWindows,
> -    IN PFAT_WINDOW SwitchToWindow OPTIONAL,
> -    IN PULONG BitMapBuffer OPTIONAL
> -    )
> -/*++
> -
> -Routine Description:
> -
> -    This routine handles scanning a segment of the FAT into in-memory
> structures.
> -
> -    There are three fundamental cases, with variations depending on the
> FAT type:
> -
> -    1) During volume setup, FatSetupAllocations
> -
> ... 63110 lines suppressed ...
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.reactos.org/pipermail/ros-dev/attachments/20171124/7fdcc623/attachment-0001.html>


More information about the Ros-dev mailing list