854 lines
19 KiB
C
854 lines
19 KiB
C
/*++ BUILD Version: 0000 // Increment this if a change has global effects
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
LfsProcs.h
|
||
|
||
Abstract:
|
||
|
||
This module defines all of the globally used procedures in the Log
|
||
File Service.
|
||
|
||
Author:
|
||
|
||
Brian Andrew [BrianAn] 20-June-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#ifndef _LFSPROCS_
|
||
#define _LFSPROCS_
|
||
|
||
#include <ntifs.h>
|
||
#include <string.h>
|
||
#include <lfs.h>
|
||
|
||
#include "nodetype.h"
|
||
#include "LfsDisk.h"
|
||
#include "LfsStruc.h"
|
||
#include "LfsData.h"
|
||
|
||
//
|
||
// Tag all of our allocations if tagging is turned on
|
||
//
|
||
|
||
#undef FsRtlAllocatePool
|
||
#undef FsRtlAllocatePoolWithQuota
|
||
|
||
#define FsRtlAllocatePool(a,b) FsRtlAllocatePoolWithTag(a,b,' sfL')
|
||
#define FsRtlAllocatePoolWithQuota(a,b) FsRtlAllocatePoolWithQuotaTag(a,b,' sfL')
|
||
|
||
#define LfsAllocatePoolNoRaise(a,b) ExAllocatePoolWithTag((a),(b),MODULE_POOL_TAG)
|
||
#define LfsAllocatePool(a,b) ExAllocatePoolWithTag(((a) | POOL_RAISE_IF_ALLOCATION_FAILURE),(b),MODULE_POOL_TAG)
|
||
#define LfsFreePool(pv) ExFreePool(pv)
|
||
|
||
#ifndef INLINE
|
||
// definition of inline
|
||
#define INLINE __inline
|
||
#endif
|
||
|
||
|
||
//
|
||
// The following routines provide an interface with the cache package.
|
||
// They are contained in 'CacheSup.c'.
|
||
//
|
||
|
||
NTSTATUS
|
||
LfsPinOrMapData (
|
||
IN PLFCB Lfcb,
|
||
IN LONGLONG FileOffset,
|
||
IN ULONG Length,
|
||
IN BOOLEAN PinData,
|
||
IN BOOLEAN AllowErrors,
|
||
IN BOOLEAN IgnoreUsaErrors,
|
||
OUT PBOOLEAN UsaError,
|
||
OUT PVOID *Buffer,
|
||
OUT PBCB *Bcb
|
||
);
|
||
|
||
//
|
||
// VOID
|
||
// LfsPreparePinWriteData (
|
||
// IN PLFCB Lfcb,
|
||
// IN LONGLONG FileOffset,
|
||
// IN ULONG Length,
|
||
// IN LOGICAL ReadFromDisk,
|
||
// OUT PVOID *Buffer,
|
||
// OUT PBCB *Bcb
|
||
// );
|
||
//
|
||
|
||
#ifdef LFS_CLUSTER_CHECK
|
||
#define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
|
||
LONGLONG _LocalFileOffset = (FO); \
|
||
CcPinRead( (L)->FileObject, \
|
||
(PLARGE_INTEGER)&_LocalFileOffset, \
|
||
(LEN), \
|
||
TRUE, \
|
||
(B), \
|
||
(BUF) ); \
|
||
}
|
||
#else
|
||
#define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
|
||
LONGLONG _LocalFileOffset = (FO); \
|
||
if (R) { \
|
||
CcPinRead( (L)->FileObject, \
|
||
(PLARGE_INTEGER)&_LocalFileOffset, \
|
||
(LEN), \
|
||
TRUE, \
|
||
(B), \
|
||
(BUF) ); \
|
||
} else { \
|
||
CcPreparePinWrite( (L)->FileObject, \
|
||
(PLARGE_INTEGER)&_LocalFileOffset, \
|
||
(LEN), \
|
||
FALSE, \
|
||
TRUE, \
|
||
(B), \
|
||
(BUF) ); \
|
||
} \
|
||
}
|
||
#endif
|
||
|
||
VOID
|
||
LfsPinOrMapLogRecordHeader (
|
||
IN PLFCB Lfcb,
|
||
IN LSN Lsn,
|
||
IN BOOLEAN PinData,
|
||
IN BOOLEAN IgnoreUsaErrors,
|
||
OUT PBOOLEAN UsaError,
|
||
OUT PLFS_RECORD_HEADER *RecordHeader,
|
||
OUT PBCB *Bcb
|
||
);
|
||
|
||
VOID
|
||
LfsCopyReadLogRecord (
|
||
IN PLFCB Lfcb,
|
||
IN PLFS_RECORD_HEADER RecordHeader,
|
||
OUT PVOID Buffer
|
||
);
|
||
|
||
VOID
|
||
LfsFlushLfcb (
|
||
IN PLFCB Lfcb,
|
||
IN LSN TargetLsn,
|
||
IN BOOLEAN RestartLsn
|
||
);
|
||
|
||
BOOLEAN
|
||
LfsReadRestart (
|
||
IN PLFCB Lfcb,
|
||
IN LONGLONG FileSize,
|
||
IN BOOLEAN FirstRestart,
|
||
OUT PLONGLONG RestartPageOffset,
|
||
OUT PLFS_RESTART_PAGE_HEADER *RestartPage,
|
||
OUT PBCB *RestartPageBcb,
|
||
OUT PBOOLEAN ChkdskWasRun,
|
||
OUT PBOOLEAN ValidPage,
|
||
OUT PBOOLEAN UninitializedFile,
|
||
OUT PBOOLEAN LogPacked,
|
||
OUT PLSN LastLsn
|
||
);
|
||
|
||
|
||
//
|
||
// The following routines manipulate buffer control blocks. They are
|
||
// contained in 'LbcbSup.c'
|
||
//
|
||
|
||
VOID
|
||
LfsFlushLbcb (
|
||
IN PLFCB Lfcb,
|
||
IN PLBCB Lbcb
|
||
);
|
||
|
||
VOID
|
||
LfsFlushToLsnPriv (
|
||
IN PLFCB Lfcb,
|
||
IN LSN Lsn,
|
||
IN BOOLEAN RestartLsn
|
||
);
|
||
|
||
PLBCB
|
||
LfsGetLbcb (
|
||
IN PLFCB Lfcb
|
||
);
|
||
|
||
|
||
//
|
||
// The following routines are in LfsData.c
|
||
//
|
||
|
||
LONG
|
||
LfsExceptionFilter (
|
||
IN PEXCEPTION_POINTERS ExceptionPointer
|
||
);
|
||
|
||
|
||
//
|
||
// Log page support routines. The following routines manipulate and
|
||
// modify log pages. They are contained in 'LogPgSup.c'
|
||
//
|
||
|
||
//
|
||
// VOID
|
||
// LfsTruncateOffsetToLogPage (
|
||
// IN PLFCB Lfcb,
|
||
// IN LONGLONG LargeInt,
|
||
// OUT PLONGLONG Result
|
||
// );
|
||
//
|
||
// ULONG
|
||
// LfsLogPageOffset (
|
||
// IN PLFCB Lfcb,
|
||
// IN ULONG Integer
|
||
// );
|
||
//
|
||
|
||
#define LfsTruncateOffsetToLogPage(LFCB,LI,OUTLI) \
|
||
*(OUTLI) = LI; \
|
||
*((PULONG)(OUTLI)) &= (LFCB)->LogPageInverseMask
|
||
|
||
#define LfsLogPageOffset(LFCB,INT) \
|
||
(INT & (LFCB)->LogPageMask)
|
||
|
||
VOID
|
||
LfsNextLogPageOffset (
|
||
IN PLFCB Lfcb,
|
||
IN LONGLONG CurrentLogPageOffset,
|
||
OUT PLONGLONG NextLogPageOffset,
|
||
OUT PBOOLEAN Wrapped
|
||
);
|
||
|
||
PVOID
|
||
LfsAllocateSpanningBuffer (
|
||
IN PLFCB Lfcb,
|
||
IN ULONG Length
|
||
);
|
||
|
||
VOID
|
||
LfsFreeSpanningBuffer (
|
||
IN PVOID Buffer
|
||
);
|
||
|
||
|
||
//
|
||
// The following routines provide support for dealing with log records. They
|
||
// are contained in 'LogRcSup.c'
|
||
//
|
||
|
||
BOOLEAN
|
||
LfsWriteLogRecordIntoLogPage (
|
||
IN PLFCB Lfcb,
|
||
IN PLCH Lch,
|
||
IN ULONG NumberOfWriteEntries,
|
||
IN PLFS_WRITE_ENTRY WriteEntries,
|
||
IN LFS_RECORD_TYPE RecordType,
|
||
IN TRANSACTION_ID *TransactionId OPTIONAL,
|
||
IN LSN ClientUndoNextLsn OPTIONAL,
|
||
IN LSN ClientPreviousLsn OPTIONAL,
|
||
IN LONG UndoRequirement,
|
||
IN BOOLEAN ForceToDisk,
|
||
OUT PLSN Lsn
|
||
);
|
||
|
||
|
||
//
|
||
// Lsn support routines. The following routines provide support for
|
||
// manipulating Lsn values. They are contained in 'LsnSup.c'
|
||
//
|
||
|
||
//
|
||
// LSN
|
||
// LfsFileOffsetToLsn (
|
||
// IN PLFCB Lfcb,
|
||
// IN LONGLONG FileOffset,
|
||
// IN LONGLONG SequenceNumber
|
||
// );
|
||
//
|
||
// BOOLEAN
|
||
// LfsIsLsnInFile (
|
||
// IN PLFCB Lfcb,
|
||
// IN LSN Lsn
|
||
// );
|
||
//
|
||
// LSN
|
||
// LfsComputeLsnFromLbcb (
|
||
// IN PLFCB Lfcb,
|
||
// IN PLBCB Lbcb
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsTruncateLsnToLogPage (
|
||
// IN PLFCB Lfcb,
|
||
// IN LSN Lsn,
|
||
// OUT PLONGLONG FileOffset
|
||
// );
|
||
//
|
||
// LONGLONG
|
||
// LfsLsnToFileOffset (
|
||
// IN PLFCB Lfcb,
|
||
// IN LSN Lsn
|
||
// );
|
||
//
|
||
// LONGLONG
|
||
// LfsLsnToSeqNumber (
|
||
// IN PLFCB Lfcb,
|
||
// IN LSN Lsn
|
||
// );
|
||
//
|
||
// ULONG
|
||
// LfsLsnToPageOffset (
|
||
// IN PLFCB Lfcb,
|
||
// IN LSN Lsn
|
||
// );
|
||
//
|
||
|
||
#define LfsFileOffsetToLsn(LFCB,FO,SN) ( \
|
||
(((ULONGLONG)(FO)) >> 3) + Int64ShllMod32((SN), (LFCB)->FileDataBits) \
|
||
)
|
||
|
||
#define LfsIsLsnInFile(LFCB,LSN) \
|
||
(/*xxGeq*/( (LSN).QuadPart >= ((LFCB)->OldestLsn).QuadPart ) \
|
||
&& /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ))
|
||
|
||
#define LfsComputeLsnFromLbcb(LFCB,LBCB) ( \
|
||
LfsFileOffsetToLsn( LFCB, \
|
||
(LBCB)->FileOffset + (LBCB)->BufferOffset, \
|
||
(LBCB)->SeqNumber ) \
|
||
)
|
||
|
||
#define LfsTruncateLsnToLogPage(LFCB,LSN,FO) { \
|
||
*(FO) = LfsLsnToFileOffset( LFCB, LSN ); \
|
||
*((PULONG)(FO)) &= (LFCB)->LogPageInverseMask; \
|
||
}
|
||
|
||
#define LfsLsnToFileOffset(LFCB,LSN) \
|
||
/*xxShr*/( ((ULONGLONG)/*xxShl*/( (LSN).QuadPart << (LFCB)->SeqNumberBits )) >> ((LFCB)->SeqNumberBits - 3) )
|
||
|
||
#define LfsLsnToSeqNumber(LFCB,LSN) \
|
||
/*xxShr*/Int64ShrlMod32( ((ULONGLONG)(LSN).QuadPart), (LFCB)->FileDataBits )
|
||
|
||
#define LfsLsnToPageOffset(LFCB,LSN) \
|
||
LfsLogPageOffset( LFCB, (LSN).LowPart << 3 )
|
||
|
||
VOID
|
||
LfsLsnFinalOffset (
|
||
IN PLFCB Lfcb,
|
||
IN LSN Lsn,
|
||
IN ULONG DataLength,
|
||
OUT PLONGLONG FinalOffset
|
||
);
|
||
|
||
BOOLEAN
|
||
LfsFindNextLsn (
|
||
IN PLFCB Lfcb,
|
||
IN PLFS_RECORD_HEADER RecordHeader,
|
||
OUT PLSN Lsn
|
||
);
|
||
|
||
|
||
//
|
||
// The following routines support the Lfs restart areas. They are contained
|
||
// in 'RstrtSup.c'
|
||
//
|
||
|
||
VOID
|
||
LfsWriteLfsRestart (
|
||
IN PLFCB Lfcb,
|
||
IN ULONG ThisRestartSize,
|
||
IN BOOLEAN WaitForIo
|
||
);
|
||
|
||
VOID
|
||
LfsFindOldestClientLsn (
|
||
IN PLFS_RESTART_AREA RestartArea,
|
||
IN PLFS_CLIENT_RECORD ClientArray,
|
||
OUT PLSN OldestLsn
|
||
);
|
||
|
||
|
||
//
|
||
// The following routines are used for managing the structures allocated
|
||
// by us. They are contained in 'StrucSup.c'
|
||
//
|
||
|
||
PLFCB
|
||
LfsAllocateLfcb (
|
||
IN ULONG LogPageSize,
|
||
IN LONGLONG FileSize
|
||
);
|
||
|
||
|
||
VOID
|
||
LfsDeallocateLfcb (
|
||
IN PLFCB Lfcb,
|
||
IN BOOLEAN CompleteTeardown
|
||
);
|
||
|
||
VOID
|
||
LfsAllocateLbcb (
|
||
IN PLFCB Lfcb,
|
||
OUT PLBCB *Lbcb
|
||
);
|
||
|
||
VOID
|
||
LfsDeallocateLbcb (
|
||
IN PLFCB Lfcb,
|
||
IN PLBCB Lbcb
|
||
);
|
||
|
||
VOID
|
||
LfsAllocateLeb (
|
||
IN PLFCB Lfcb,
|
||
OUT PLEB *NewLeb
|
||
);
|
||
|
||
VOID
|
||
LfsDeallocateLeb (
|
||
IN PLFCB Lfcb,
|
||
IN PLEB Leb
|
||
);
|
||
|
||
VOID
|
||
LfsReadPage (
|
||
IN PLFCB Lfcb,
|
||
IN PLARGE_INTEGER Offset,
|
||
OUT PMDL *Mdl,
|
||
OUT PVOID *Buffer
|
||
);
|
||
|
||
//
|
||
// VOID
|
||
// LfsInitializeLeb (
|
||
// IN PLEB Leb,
|
||
// IN LFS_CLIENT_ID ClientId,
|
||
// IN LFS_CONTEXT_MODE ContextMode
|
||
// );
|
||
//
|
||
//
|
||
// VOID
|
||
// LfsAllocateLch (
|
||
// OUT PLCH *Lch
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsDeallocateLch (
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsAllocateRestartArea (
|
||
// OUT PLFS_RESTART_AREA *RestartArea,
|
||
// ULONG Size
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsDeallocateRestartArea (
|
||
// IN PLFS_RESTART_AREA RestartArea
|
||
// );
|
||
//
|
||
// BOOLEAN
|
||
// LfsLbcbIsRestart (
|
||
// IN PLBCB Lbcb
|
||
// );
|
||
//
|
||
|
||
#define LfsInitializeLeb(LEB,ID,MODE) \
|
||
(LEB)->ClientId = ID; \
|
||
(LEB)->ContextMode = MODE
|
||
|
||
|
||
#define LfsAllocateLch(NEW) { \
|
||
*(NEW) = FsRtlAllocatePool( PagedPool, sizeof( LCH )); \
|
||
RtlZeroMemory( (*NEW), sizeof( LCH )); \
|
||
(*(NEW))->NodeTypeCode = LFS_NTC_LCH; \
|
||
(*(NEW))->NodeByteSize = sizeof( LCH ); \
|
||
}
|
||
|
||
#define LfsDeallocateLch(LCH) \
|
||
ExFreePool( LCH )
|
||
|
||
#define LfsAllocateRestartArea(RS,SIZE) \
|
||
*(RS) = FsRtlAllocatePool( PagedPool, (SIZE) ); \
|
||
RtlZeroMemory( *(RS), (SIZE) )
|
||
|
||
#define LfsDeallocateRestartArea(RS) \
|
||
ExFreePool( RS )
|
||
|
||
#define LfsLbcbIsRestart(LBCB) \
|
||
(FlagOn( (LBCB)->LbcbFlags, LBCB_RESTART_LBCB ))
|
||
|
||
|
||
//
|
||
// The following routines provide synchronization support for the Lfs
|
||
// shared structures. They are contained in 'SyncSup.c'
|
||
//
|
||
|
||
//
|
||
// VOID
|
||
// LfsAcquireLfsData (
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsReleaseLfsData (
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsAcquireLfcb (
|
||
// IN PLFCB Lfcb
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsReleaseLfcb (
|
||
// IN PLFCB Lfcb
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsAcquireLchExclusive (
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsAcquireLchShared (
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsReleaseLfcb (
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
|
||
#define LfsAcquireLfsData() \
|
||
ExAcquireFastMutex( &LfsData.LfsDataLock )
|
||
|
||
#define LfsReleaseLfsData() \
|
||
ExReleaseFastMutex( &LfsData.LfsDataLock )
|
||
|
||
#define LfsAcquireBufferLock() \
|
||
ExAcquireFastMutex( &LfsData.BufferLock )
|
||
|
||
#define LfsReleaseBufferLock() \
|
||
ExReleaseFastMutex( &LfsData.BufferLock )
|
||
|
||
#define LfsWaitForBufferNotification() \
|
||
KeWaitForSingleObject( &LfsData.BufferNotification, \
|
||
Executive, \
|
||
KernelMode, \
|
||
FALSE, \
|
||
NULL )
|
||
|
||
#define LfsNotifyBufferWaiters() \
|
||
KeSetEvent( &LfsData.BufferNotification, 0, FALSE )
|
||
|
||
#define LfsBlockBufferWaiters() \
|
||
KeClearEvent( &LfsData.BufferNotification )
|
||
|
||
INLINE
|
||
VOID
|
||
LfsAcquireLfcbExclusive (
|
||
IN PLFCB Lfcb
|
||
)
|
||
{
|
||
ExAcquireResourceExclusiveLite( &Lfcb->Sync->Resource, TRUE );
|
||
}
|
||
|
||
INLINE
|
||
VOID
|
||
LfsAcquireLfcbShared (
|
||
IN PLFCB Lfcb
|
||
)
|
||
{
|
||
ExAcquireResourceSharedLite( &Lfcb->Sync->Resource, TRUE );
|
||
}
|
||
|
||
|
||
INLINE
|
||
VOID
|
||
LfsReleaseLfcb (
|
||
IN PLFCB Lfcb
|
||
)
|
||
{
|
||
//
|
||
// If the resource is owned either shared or exlcusive release it
|
||
//
|
||
|
||
if (ExIsResourceAcquiredSharedLite( &Lfcb->Sync->Resource )) {
|
||
ExReleaseResourceLite( &Lfcb->Sync->Resource );
|
||
}
|
||
}
|
||
|
||
INLINE
|
||
VOID
|
||
LfsAcquireLchExclusive (
|
||
IN PLCH Lch
|
||
)
|
||
{
|
||
ExAcquireResourceExclusiveLite( &(Lch->Sync->Resource), TRUE );
|
||
}
|
||
|
||
INLINE
|
||
VOID
|
||
LfsAcquireLchShared (
|
||
IN PLCH Lch
|
||
)
|
||
{
|
||
ExAcquireResourceSharedLite( &(Lch->Sync->Resource), TRUE );
|
||
}
|
||
|
||
|
||
INLINE
|
||
VOID
|
||
LfsReleaseLch (
|
||
IN PLCH Lch
|
||
)
|
||
{
|
||
if (ExIsResourceAcquiredSharedLite( &Lch->Sync->Resource )) {
|
||
ExReleaseResourceLite( &Lch->Sync->Resource );
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// The following routines are used to check various structures for validity
|
||
// and comparability. They are contained in 'VerfySup.c'.
|
||
//
|
||
|
||
VOID
|
||
LfsCurrentAvailSpace (
|
||
IN PLFCB Lfcb,
|
||
OUT PLONGLONG CurrentAvailSpace,
|
||
OUT PULONG CurrentPageBytes
|
||
);
|
||
|
||
BOOLEAN
|
||
LfsVerifyLogSpaceAvail (
|
||
IN PLFCB Lfcb,
|
||
IN PLCH Lch,
|
||
IN ULONG RemainingLogBytes,
|
||
IN LONG UndoRequirement,
|
||
IN BOOLEAN ForceToDisk
|
||
);
|
||
|
||
VOID
|
||
LfsFindCurrentAvail (
|
||
IN PLFCB Lfcb
|
||
);
|
||
|
||
BOOLEAN
|
||
LfsCheckSubsequentLogPage (
|
||
IN PLFCB Lfcb,
|
||
IN PLFS_RECORD_PAGE_HEADER RecordPageHeader,
|
||
IN LONGLONG LogFileOffset,
|
||
IN LONGLONG SequenceNumber
|
||
);
|
||
|
||
|
||
//
|
||
// VOID
|
||
// LfsValidateLch (
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
// VOID
|
||
// LfsValidateClientId (
|
||
// IN PLFCB Lfcb,
|
||
// IN PLCH Lch
|
||
// );
|
||
//
|
||
// BOOLEAN
|
||
// LfsVerifyClientLsnInRange (
|
||
// IN PLFCB Lfcb,
|
||
// IN PLFS_CLIENT_RECORD ClientRecord,
|
||
// IN LSN Lsn
|
||
// );
|
||
//
|
||
// BOOLEAN
|
||
// LfsClientIdMatch (
|
||
// IN PLFS_CLIENT_ID ClientA,
|
||
// IN PLFS_CLIENT_ID ClientB
|
||
// )
|
||
//
|
||
// VOID
|
||
// LfsValidateLeb (
|
||
// IN PLFS_CONTEXT_BLOCK Leb,
|
||
// IN PLCH Lch
|
||
// )
|
||
//
|
||
|
||
#define LfsValidateLch(LCH) \
|
||
if ((LCH) == NULL \
|
||
|| (LCH)->NodeTypeCode != LFS_NTC_LCH \
|
||
|| ((LCH)->Lfcb != NULL \
|
||
&& (LCH)->Lfcb->NodeTypeCode != LFS_NTC_LFCB)) { \
|
||
\
|
||
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
|
||
}
|
||
|
||
#define LfsValidateClientId(LFCB,LCH) \
|
||
if ((LCH)->ClientId.ClientIndex >= (LFCB)->RestartArea->LogClients \
|
||
|| (LCH)->ClientId.SeqNumber \
|
||
!= Add2Ptr( Lfcb->ClientArray, \
|
||
(LCH)->ClientArrayByteOffset, \
|
||
PLFS_CLIENT_RECORD )->SeqNumber) { \
|
||
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
|
||
}
|
||
|
||
#define LfsVerifyClientLsnInRange(LFCB,CLIENT,LSN) \
|
||
(/*xxGeq*/( (LSN).QuadPart >= ((CLIENT)->OldestLsn).QuadPart ) \
|
||
&& /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ) \
|
||
&& /*xxNeqZero*/( (LSN).QuadPart != 0 ))
|
||
|
||
#define LfsClientIdMatch(CLIENT_A,CLIENT_B) \
|
||
((BOOLEAN) ((CLIENT_A)->SeqNumber == (CLIENT_B)->SeqNumber \
|
||
&& (CLIENT_A)->ClientIndex == (CLIENT_B)->ClientIndex))
|
||
|
||
#define LfsValidateLeb(LEB,LCH) \
|
||
if (LEB == NULL \
|
||
|| (LEB)->NodeTypeCode != LFS_NTC_LEB \
|
||
|| !LfsClientIdMatch( &(LEB)->ClientId, &(LCH)->ClientId )) { \
|
||
ExRaiseStatus( STATUS_ACCESS_DENIED ); \
|
||
}
|
||
|
||
|
||
//
|
||
// Miscellaneous support routines
|
||
//
|
||
|
||
//
|
||
// ULONG
|
||
// FlagOn (
|
||
// IN ULONG Flags,
|
||
// IN ULONG SingleFlag
|
||
// );
|
||
//
|
||
// BOOLEAN
|
||
// BooleanFlagOn (
|
||
// IN ULONG Flags,
|
||
// IN ULONG SingleFlag
|
||
// );
|
||
//
|
||
// VOID
|
||
// SetFlag (
|
||
// IN ULONG Flags,
|
||
// IN ULONG SingleFlag
|
||
// );
|
||
//
|
||
// VOID
|
||
// ClearFlag (
|
||
// IN ULONG Flags,
|
||
// IN ULONG SingleFlag
|
||
// );
|
||
//
|
||
|
||
//#ifndef BooleanFlagOn
|
||
//#define BooleanFlagOn(F,SF) ( \
|
||
// (BOOLEAN)(((F) & (SF)) != 0) \
|
||
//)
|
||
//#endif
|
||
|
||
//#ifndef SetFlag
|
||
//#define SetFlag(Flags,SingleFlag) { \
|
||
// (Flags) |= (SingleFlag); \
|
||
//}
|
||
//#endif
|
||
|
||
//#ifndef ClearFlag
|
||
//#define ClearFlag(Flags,SingleFlag) { \
|
||
// (Flags) &= ~(SingleFlag); \
|
||
//}
|
||
//#endif
|
||
|
||
//
|
||
// This macro takes a pointer (or ulong) and returns its rounded up word
|
||
// value
|
||
//
|
||
|
||
#define WordAlign(Ptr) ( \
|
||
((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
|
||
)
|
||
|
||
//
|
||
// This macro takes a pointer (or ulong) and returns its rounded up longword
|
||
// value
|
||
//
|
||
|
||
#define LongAlign(Ptr) ( \
|
||
((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
|
||
)
|
||
|
||
//
|
||
// This macro takes a pointer (or ulong) and returns its rounded up quadword
|
||
// value
|
||
//
|
||
|
||
#define QuadAlign(Ptr) ( \
|
||
((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
|
||
)
|
||
|
||
//
|
||
// This macro will up a 64 bit value to the next quad align boundary.
|
||
//
|
||
|
||
#define LiQuadAlign(LI,OUT) { \
|
||
*(OUT) = /*xxAdd*/( (LI) + 7 ); \
|
||
*((PULONG)(OUT)) &= 0xfffffff8; \
|
||
}
|
||
|
||
//
|
||
// CAST
|
||
// Add2Ptr (
|
||
// IN PVOID Pointer,
|
||
// IN ULONG Increment
|
||
// IN (CAST)
|
||
// );
|
||
//
|
||
// ULONG
|
||
// PtrOffset (
|
||
// IN PVOID BasePtr,
|
||
// IN PVOID OffsetPtr
|
||
// );
|
||
//
|
||
|
||
#define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
|
||
|
||
#define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
|
||
|
||
|
||
//
|
||
// The following macros are used to establish the semantics needed
|
||
// to do a return from within a try-finally clause. As a rule every
|
||
// try clause must end with a label call try_exit. For example,
|
||
//
|
||
// try {
|
||
// :
|
||
// :
|
||
//
|
||
// try_exit: NOTHING;
|
||
// } finally {
|
||
//
|
||
// :
|
||
// :
|
||
// }
|
||
//
|
||
// Every return statement executed inside of a try clause should use the
|
||
// try_return macro. If the compiler fully supports the try-finally construct
|
||
// then the macro should be
|
||
//
|
||
// #define try_return(S) { return(S); }
|
||
//
|
||
// If the compiler does not support the try-finally construct then the macro
|
||
// should be
|
||
//
|
||
// #define try_return(S) { S; goto try_exit; }
|
||
//
|
||
|
||
#define try_return(S) { S; goto try_exit; }
|
||
|
||
#endif // _LFSPROCS_
|