mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
822 lines
19 KiB
822 lines
19 KiB
/*++ 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 PLBCB Lbcb
|
|
);
|
|
|
|
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
|
|
);
|
|
|
|
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
|
|
// LfsAcquireLch (
|
|
// 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
|
|
LfsAcquireLfcb (
|
|
IN PLFCB Lfcb
|
|
)
|
|
{
|
|
ExAcquireResourceExclusiveLite( &Lfcb->Sync->Resource, TRUE );
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
LfsReleaseLfcb (
|
|
IN PLFCB Lfcb
|
|
)
|
|
{
|
|
if (Lfcb->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
|
|
ExReleaseResourceLite( &Lfcb->Sync->Resource );
|
|
}
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
LfsAcquireLch (
|
|
IN PLCH Lch
|
|
)
|
|
{
|
|
ExAcquireResourceExclusiveLite( &(Lch->Sync->Resource), TRUE );
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
LfsReleaseLch (
|
|
IN PLCH Lch
|
|
)
|
|
{
|
|
if (Lch->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
|
|
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_
|