Source code of Windows XP (NT5)
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

  1. /*++ BUILD Version: 0000 // Increment this if a change has global effects
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. LfsProcs.h
  5. Abstract:
  6. This module defines all of the globally used procedures in the Log
  7. File Service.
  8. Author:
  9. Brian Andrew [BrianAn] 20-June-1991
  10. Revision History:
  11. --*/
  12. #ifndef _LFSPROCS_
  13. #define _LFSPROCS_
  14. #include <ntifs.h>
  15. #include <string.h>
  16. #include <lfs.h>
  17. #include "nodetype.h"
  18. #include "LfsDisk.h"
  19. #include "LfsStruc.h"
  20. #include "LfsData.h"
  21. //
  22. // Tag all of our allocations if tagging is turned on
  23. //
  24. #undef FsRtlAllocatePool
  25. #undef FsRtlAllocatePoolWithQuota
  26. #define FsRtlAllocatePool(a,b) FsRtlAllocatePoolWithTag(a,b,' sfL')
  27. #define FsRtlAllocatePoolWithQuota(a,b) FsRtlAllocatePoolWithQuotaTag(a,b,' sfL')
  28. #define LfsAllocatePoolNoRaise(a,b) ExAllocatePoolWithTag((a),(b),MODULE_POOL_TAG)
  29. #define LfsAllocatePool(a,b) ExAllocatePoolWithTag(((a) | POOL_RAISE_IF_ALLOCATION_FAILURE),(b),MODULE_POOL_TAG)
  30. #define LfsFreePool(pv) ExFreePool(pv)
  31. #ifndef INLINE
  32. // definition of inline
  33. #define INLINE __inline
  34. #endif
  35. //
  36. // The following routines provide an interface with the cache package.
  37. // They are contained in 'CacheSup.c'.
  38. //
  39. NTSTATUS
  40. LfsPinOrMapData (
  41. IN PLFCB Lfcb,
  42. IN LONGLONG FileOffset,
  43. IN ULONG Length,
  44. IN BOOLEAN PinData,
  45. IN BOOLEAN AllowErrors,
  46. IN BOOLEAN IgnoreUsaErrors,
  47. OUT PBOOLEAN UsaError,
  48. OUT PVOID *Buffer,
  49. OUT PBCB *Bcb
  50. );
  51. //
  52. // VOID
  53. // LfsPreparePinWriteData (
  54. // IN PLFCB Lfcb,
  55. // IN LONGLONG FileOffset,
  56. // IN ULONG Length,
  57. // IN LOGICAL ReadFromDisk,
  58. // OUT PVOID *Buffer,
  59. // OUT PBCB *Bcb
  60. // );
  61. //
  62. #ifdef LFS_CLUSTER_CHECK
  63. #define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
  64. LONGLONG _LocalFileOffset = (FO); \
  65. CcPinRead( (L)->FileObject, \
  66. (PLARGE_INTEGER)&_LocalFileOffset, \
  67. (LEN), \
  68. TRUE, \
  69. (B), \
  70. (BUF) ); \
  71. }
  72. #else
  73. #define LfsPreparePinWriteData(L,FO,LEN,R,BUF,B) { \
  74. LONGLONG _LocalFileOffset = (FO); \
  75. if (R) { \
  76. CcPinRead( (L)->FileObject, \
  77. (PLARGE_INTEGER)&_LocalFileOffset, \
  78. (LEN), \
  79. TRUE, \
  80. (B), \
  81. (BUF) ); \
  82. } else { \
  83. CcPreparePinWrite( (L)->FileObject, \
  84. (PLARGE_INTEGER)&_LocalFileOffset, \
  85. (LEN), \
  86. FALSE, \
  87. TRUE, \
  88. (B), \
  89. (BUF) ); \
  90. } \
  91. }
  92. #endif
  93. VOID
  94. LfsPinOrMapLogRecordHeader (
  95. IN PLFCB Lfcb,
  96. IN LSN Lsn,
  97. IN BOOLEAN PinData,
  98. IN BOOLEAN IgnoreUsaErrors,
  99. OUT PBOOLEAN UsaError,
  100. OUT PLFS_RECORD_HEADER *RecordHeader,
  101. OUT PBCB *Bcb
  102. );
  103. VOID
  104. LfsCopyReadLogRecord (
  105. IN PLFCB Lfcb,
  106. IN PLFS_RECORD_HEADER RecordHeader,
  107. OUT PVOID Buffer
  108. );
  109. VOID
  110. LfsFlushLfcb (
  111. IN PLFCB Lfcb,
  112. IN PLBCB Lbcb
  113. );
  114. BOOLEAN
  115. LfsReadRestart (
  116. IN PLFCB Lfcb,
  117. IN LONGLONG FileSize,
  118. IN BOOLEAN FirstRestart,
  119. OUT PLONGLONG RestartPageOffset,
  120. OUT PLFS_RESTART_PAGE_HEADER *RestartPage,
  121. OUT PBCB *RestartPageBcb,
  122. OUT PBOOLEAN ChkdskWasRun,
  123. OUT PBOOLEAN ValidPage,
  124. OUT PBOOLEAN UninitializedFile,
  125. OUT PBOOLEAN LogPacked,
  126. OUT PLSN LastLsn
  127. );
  128. //
  129. // The following routines manipulate buffer control blocks. They are
  130. // contained in 'LbcbSup.c'
  131. //
  132. VOID
  133. LfsFlushLbcb (
  134. IN PLFCB Lfcb,
  135. IN PLBCB Lbcb
  136. );
  137. VOID
  138. LfsFlushToLsnPriv (
  139. IN PLFCB Lfcb,
  140. IN LSN Lsn
  141. );
  142. PLBCB
  143. LfsGetLbcb (
  144. IN PLFCB Lfcb
  145. );
  146. //
  147. // The following routines are in LfsData.c
  148. //
  149. LONG
  150. LfsExceptionFilter (
  151. IN PEXCEPTION_POINTERS ExceptionPointer
  152. );
  153. //
  154. // Log page support routines. The following routines manipulate and
  155. // modify log pages. They are contained in 'LogPgSup.c'
  156. //
  157. //
  158. // VOID
  159. // LfsTruncateOffsetToLogPage (
  160. // IN PLFCB Lfcb,
  161. // IN LONGLONG LargeInt,
  162. // OUT PLONGLONG Result
  163. // );
  164. //
  165. // ULONG
  166. // LfsLogPageOffset (
  167. // IN PLFCB Lfcb,
  168. // IN ULONG Integer
  169. // );
  170. //
  171. #define LfsTruncateOffsetToLogPage(LFCB,LI,OUTLI) \
  172. *(OUTLI) = LI; \
  173. *((PULONG)(OUTLI)) &= (LFCB)->LogPageInverseMask
  174. #define LfsLogPageOffset(LFCB,INT) \
  175. (INT & (LFCB)->LogPageMask)
  176. VOID
  177. LfsNextLogPageOffset (
  178. IN PLFCB Lfcb,
  179. IN LONGLONG CurrentLogPageOffset,
  180. OUT PLONGLONG NextLogPageOffset,
  181. OUT PBOOLEAN Wrapped
  182. );
  183. PVOID
  184. LfsAllocateSpanningBuffer (
  185. IN PLFCB Lfcb,
  186. IN ULONG Length
  187. );
  188. VOID
  189. LfsFreeSpanningBuffer (
  190. IN PVOID Buffer
  191. );
  192. //
  193. // The following routines provide support for dealing with log records. They
  194. // are contained in 'LogRcSup.c'
  195. //
  196. BOOLEAN
  197. LfsWriteLogRecordIntoLogPage (
  198. IN PLFCB Lfcb,
  199. IN PLCH Lch,
  200. IN ULONG NumberOfWriteEntries,
  201. IN PLFS_WRITE_ENTRY WriteEntries,
  202. IN LFS_RECORD_TYPE RecordType,
  203. IN TRANSACTION_ID *TransactionId OPTIONAL,
  204. IN LSN ClientUndoNextLsn OPTIONAL,
  205. IN LSN ClientPreviousLsn OPTIONAL,
  206. IN LONG UndoRequirement,
  207. IN BOOLEAN ForceToDisk,
  208. OUT PLSN Lsn
  209. );
  210. //
  211. // Lsn support routines. The following routines provide support for
  212. // manipulating Lsn values. They are contained in 'LsnSup.c'
  213. //
  214. //
  215. // LSN
  216. // LfsFileOffsetToLsn (
  217. // IN PLFCB Lfcb,
  218. // IN LONGLONG FileOffset,
  219. // IN LONGLONG SequenceNumber
  220. // );
  221. //
  222. // BOOLEAN
  223. // LfsIsLsnInFile (
  224. // IN PLFCB Lfcb,
  225. // IN LSN Lsn
  226. // );
  227. //
  228. // LSN
  229. // LfsComputeLsnFromLbcb (
  230. // IN PLFCB Lfcb,
  231. // IN PLBCB Lbcb
  232. // );
  233. //
  234. // VOID
  235. // LfsTruncateLsnToLogPage (
  236. // IN PLFCB Lfcb,
  237. // IN LSN Lsn,
  238. // OUT PLONGLONG FileOffset
  239. // );
  240. //
  241. // LONGLONG
  242. // LfsLsnToFileOffset (
  243. // IN PLFCB Lfcb,
  244. // IN LSN Lsn
  245. // );
  246. //
  247. // LONGLONG
  248. // LfsLsnToSeqNumber (
  249. // IN PLFCB Lfcb,
  250. // IN LSN Lsn
  251. // );
  252. //
  253. // ULONG
  254. // LfsLsnToPageOffset (
  255. // IN PLFCB Lfcb,
  256. // IN LSN Lsn
  257. // );
  258. //
  259. #define LfsFileOffsetToLsn(LFCB,FO,SN) ( \
  260. (((ULONGLONG)(FO)) >> 3) + Int64ShllMod32((SN), (LFCB)->FileDataBits) \
  261. )
  262. #define LfsIsLsnInFile(LFCB,LSN) \
  263. (/*xxGeq*/( (LSN).QuadPart >= ((LFCB)->OldestLsn).QuadPart ) \
  264. && /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ))
  265. #define LfsComputeLsnFromLbcb(LFCB,LBCB) ( \
  266. LfsFileOffsetToLsn( LFCB, \
  267. (LBCB)->FileOffset + (LBCB)->BufferOffset, \
  268. (LBCB)->SeqNumber ) \
  269. )
  270. #define LfsTruncateLsnToLogPage(LFCB,LSN,FO) { \
  271. *(FO) = LfsLsnToFileOffset( LFCB, LSN ); \
  272. *((PULONG)(FO)) &= (LFCB)->LogPageInverseMask; \
  273. }
  274. #define LfsLsnToFileOffset(LFCB,LSN) \
  275. /*xxShr*/( ((ULONGLONG)/*xxShl*/( (LSN).QuadPart << (LFCB)->SeqNumberBits )) >> ((LFCB)->SeqNumberBits - 3) )
  276. #define LfsLsnToSeqNumber(LFCB,LSN) \
  277. /*xxShr*/Int64ShrlMod32( ((ULONGLONG)(LSN).QuadPart), (LFCB)->FileDataBits )
  278. #define LfsLsnToPageOffset(LFCB,LSN) \
  279. LfsLogPageOffset( LFCB, (LSN).LowPart << 3 )
  280. VOID
  281. LfsLsnFinalOffset (
  282. IN PLFCB Lfcb,
  283. IN LSN Lsn,
  284. IN ULONG DataLength,
  285. OUT PLONGLONG FinalOffset
  286. );
  287. BOOLEAN
  288. LfsFindNextLsn (
  289. IN PLFCB Lfcb,
  290. IN PLFS_RECORD_HEADER RecordHeader,
  291. OUT PLSN Lsn
  292. );
  293. //
  294. // The following routines support the Lfs restart areas. They are contained
  295. // in 'RstrtSup.c'
  296. //
  297. VOID
  298. LfsWriteLfsRestart (
  299. IN PLFCB Lfcb,
  300. IN ULONG ThisRestartSize,
  301. IN BOOLEAN WaitForIo
  302. );
  303. VOID
  304. LfsFindOldestClientLsn (
  305. IN PLFS_RESTART_AREA RestartArea,
  306. IN PLFS_CLIENT_RECORD ClientArray,
  307. OUT PLSN OldestLsn
  308. );
  309. //
  310. // The following routines are used for managing the structures allocated
  311. // by us. They are contained in 'StrucSup.c'
  312. //
  313. PLFCB
  314. LfsAllocateLfcb (
  315. IN ULONG LogPageSize,
  316. IN LONGLONG FileSize
  317. );
  318. VOID
  319. LfsDeallocateLfcb (
  320. IN PLFCB Lfcb,
  321. IN BOOLEAN CompleteTeardown
  322. );
  323. VOID
  324. LfsAllocateLbcb (
  325. IN PLFCB Lfcb,
  326. OUT PLBCB *Lbcb
  327. );
  328. VOID
  329. LfsDeallocateLbcb (
  330. IN PLFCB Lfcb,
  331. IN PLBCB Lbcb
  332. );
  333. VOID
  334. LfsAllocateLeb (
  335. IN PLFCB Lfcb,
  336. OUT PLEB *NewLeb
  337. );
  338. VOID
  339. LfsDeallocateLeb (
  340. IN PLFCB Lfcb,
  341. IN PLEB Leb
  342. );
  343. VOID
  344. LfsReadPage (
  345. IN PLFCB Lfcb,
  346. IN PLARGE_INTEGER Offset,
  347. OUT PMDL *Mdl,
  348. OUT PVOID *Buffer
  349. );
  350. //
  351. // VOID
  352. // LfsInitializeLeb (
  353. // IN PLEB Leb,
  354. // IN LFS_CLIENT_ID ClientId,
  355. // IN LFS_CONTEXT_MODE ContextMode
  356. // );
  357. //
  358. //
  359. // VOID
  360. // LfsAllocateLch (
  361. // OUT PLCH *Lch
  362. // );
  363. //
  364. // VOID
  365. // LfsDeallocateLch (
  366. // IN PLCH Lch
  367. // );
  368. //
  369. // VOID
  370. // LfsAllocateRestartArea (
  371. // OUT PLFS_RESTART_AREA *RestartArea,
  372. // ULONG Size
  373. // );
  374. //
  375. // VOID
  376. // LfsDeallocateRestartArea (
  377. // IN PLFS_RESTART_AREA RestartArea
  378. // );
  379. //
  380. // BOOLEAN
  381. // LfsLbcbIsRestart (
  382. // IN PLBCB Lbcb
  383. // );
  384. //
  385. #define LfsInitializeLeb(LEB,ID,MODE) \
  386. (LEB)->ClientId = ID; \
  387. (LEB)->ContextMode = MODE
  388. #define LfsAllocateLch(NEW) { \
  389. *(NEW) = FsRtlAllocatePool( PagedPool, sizeof( LCH )); \
  390. RtlZeroMemory( (*NEW), sizeof( LCH )); \
  391. (*(NEW))->NodeTypeCode = LFS_NTC_LCH; \
  392. (*(NEW))->NodeByteSize = sizeof( LCH ); \
  393. }
  394. #define LfsDeallocateLch(LCH) \
  395. ExFreePool( LCH )
  396. #define LfsAllocateRestartArea(RS,SIZE) \
  397. *(RS) = FsRtlAllocatePool( PagedPool, (SIZE) ); \
  398. RtlZeroMemory( *(RS), (SIZE) )
  399. #define LfsDeallocateRestartArea(RS) \
  400. ExFreePool( RS )
  401. #define LfsLbcbIsRestart(LBCB) \
  402. (FlagOn( (LBCB)->LbcbFlags, LBCB_RESTART_LBCB ))
  403. //
  404. // The following routines provide synchronization support for the Lfs
  405. // shared structures. They are contained in 'SyncSup.c'
  406. //
  407. //
  408. // VOID
  409. // LfsAcquireLfsData (
  410. // );
  411. //
  412. // VOID
  413. // LfsReleaseLfsData (
  414. // );
  415. //
  416. // VOID
  417. // LfsAcquireLfcb (
  418. // IN PLFCB Lfcb
  419. // );
  420. //
  421. // VOID
  422. // LfsReleaseLfcb (
  423. // IN PLFCB Lfcb
  424. // );
  425. //
  426. // VOID
  427. // LfsAcquireLch (
  428. // IN PLCH Lch
  429. // );
  430. //
  431. // VOID
  432. // LfsReleaseLfcb (
  433. // IN PLCH Lch
  434. // );
  435. //
  436. #define LfsAcquireLfsData() \
  437. ExAcquireFastMutex( &LfsData.LfsDataLock )
  438. #define LfsReleaseLfsData() \
  439. ExReleaseFastMutex( &LfsData.LfsDataLock )
  440. #define LfsAcquireBufferLock() \
  441. ExAcquireFastMutex( &LfsData.BufferLock )
  442. #define LfsReleaseBufferLock() \
  443. ExReleaseFastMutex( &LfsData.BufferLock )
  444. #define LfsWaitForBufferNotification() \
  445. KeWaitForSingleObject( &LfsData.BufferNotification, \
  446. Executive, \
  447. KernelMode, \
  448. FALSE, \
  449. NULL )
  450. #define LfsNotifyBufferWaiters() \
  451. KeSetEvent( &LfsData.BufferNotification, 0, FALSE )
  452. #define LfsBlockBufferWaiters() \
  453. KeClearEvent( &LfsData.BufferNotification )
  454. INLINE
  455. VOID
  456. LfsAcquireLfcb (
  457. IN PLFCB Lfcb
  458. )
  459. {
  460. ExAcquireResourceExclusiveLite( &Lfcb->Sync->Resource, TRUE );
  461. }
  462. INLINE
  463. VOID
  464. LfsReleaseLfcb (
  465. IN PLFCB Lfcb
  466. )
  467. {
  468. if (Lfcb->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
  469. ExReleaseResourceLite( &Lfcb->Sync->Resource );
  470. }
  471. }
  472. INLINE
  473. VOID
  474. LfsAcquireLch (
  475. IN PLCH Lch
  476. )
  477. {
  478. ExAcquireResourceExclusiveLite( &(Lch->Sync->Resource), TRUE );
  479. }
  480. INLINE
  481. VOID
  482. LfsReleaseLch (
  483. IN PLCH Lch
  484. )
  485. {
  486. if (Lch->Sync->Resource.OwnerThreads[0].OwnerThread == ExGetCurrentResourceThread()) {
  487. ExReleaseResourceLite( &Lch->Sync->Resource );
  488. }
  489. }
  490. //
  491. // The following routines are used to check various structures for validity
  492. // and comparability. They are contained in 'VerfySup.c'.
  493. //
  494. VOID
  495. LfsCurrentAvailSpace (
  496. IN PLFCB Lfcb,
  497. OUT PLONGLONG CurrentAvailSpace,
  498. OUT PULONG CurrentPageBytes
  499. );
  500. BOOLEAN
  501. LfsVerifyLogSpaceAvail (
  502. IN PLFCB Lfcb,
  503. IN PLCH Lch,
  504. IN ULONG RemainingLogBytes,
  505. IN LONG UndoRequirement,
  506. IN BOOLEAN ForceToDisk
  507. );
  508. VOID
  509. LfsFindCurrentAvail (
  510. IN PLFCB Lfcb
  511. );
  512. BOOLEAN
  513. LfsCheckSubsequentLogPage (
  514. IN PLFCB Lfcb,
  515. IN PLFS_RECORD_PAGE_HEADER RecordPageHeader,
  516. IN LONGLONG LogFileOffset,
  517. IN LONGLONG SequenceNumber
  518. );
  519. //
  520. // VOID
  521. // LfsValidateLch (
  522. // IN PLCH Lch
  523. // );
  524. //
  525. // VOID
  526. // LfsValidateClientId (
  527. // IN PLFCB Lfcb,
  528. // IN PLCH Lch
  529. // );
  530. //
  531. // BOOLEAN
  532. // LfsVerifyClientLsnInRange (
  533. // IN PLFCB Lfcb,
  534. // IN PLFS_CLIENT_RECORD ClientRecord,
  535. // IN LSN Lsn
  536. // );
  537. //
  538. // BOOLEAN
  539. // LfsClientIdMatch (
  540. // IN PLFS_CLIENT_ID ClientA,
  541. // IN PLFS_CLIENT_ID ClientB
  542. // )
  543. //
  544. // VOID
  545. // LfsValidateLeb (
  546. // IN PLFS_CONTEXT_BLOCK Leb,
  547. // IN PLCH Lch
  548. // )
  549. //
  550. #define LfsValidateLch(LCH) \
  551. if ((LCH) == NULL \
  552. || (LCH)->NodeTypeCode != LFS_NTC_LCH \
  553. || ((LCH)->Lfcb != NULL \
  554. && (LCH)->Lfcb->NodeTypeCode != LFS_NTC_LFCB)) { \
  555. \
  556. ExRaiseStatus( STATUS_ACCESS_DENIED ); \
  557. }
  558. #define LfsValidateClientId(LFCB,LCH) \
  559. if ((LCH)->ClientId.ClientIndex >= (LFCB)->RestartArea->LogClients \
  560. || (LCH)->ClientId.SeqNumber \
  561. != Add2Ptr( Lfcb->ClientArray, \
  562. (LCH)->ClientArrayByteOffset, \
  563. PLFS_CLIENT_RECORD )->SeqNumber) { \
  564. ExRaiseStatus( STATUS_ACCESS_DENIED ); \
  565. }
  566. #define LfsVerifyClientLsnInRange(LFCB,CLIENT,LSN) \
  567. (/*xxGeq*/( (LSN).QuadPart >= ((CLIENT)->OldestLsn).QuadPart ) \
  568. && /*xxLeq*/( (LSN).QuadPart <= ((LFCB)->RestartArea->CurrentLsn).QuadPart ) \
  569. && /*xxNeqZero*/( (LSN).QuadPart != 0 ))
  570. #define LfsClientIdMatch(CLIENT_A,CLIENT_B) \
  571. ((BOOLEAN) ((CLIENT_A)->SeqNumber == (CLIENT_B)->SeqNumber \
  572. && (CLIENT_A)->ClientIndex == (CLIENT_B)->ClientIndex))
  573. #define LfsValidateLeb(LEB,LCH) \
  574. if (LEB == NULL \
  575. || (LEB)->NodeTypeCode != LFS_NTC_LEB \
  576. || !LfsClientIdMatch( &(LEB)->ClientId, &(LCH)->ClientId )) { \
  577. ExRaiseStatus( STATUS_ACCESS_DENIED ); \
  578. }
  579. //
  580. // Miscellaneous support routines
  581. //
  582. //
  583. // ULONG
  584. // FlagOn (
  585. // IN ULONG Flags,
  586. // IN ULONG SingleFlag
  587. // );
  588. //
  589. // BOOLEAN
  590. // BooleanFlagOn (
  591. // IN ULONG Flags,
  592. // IN ULONG SingleFlag
  593. // );
  594. //
  595. // VOID
  596. // SetFlag (
  597. // IN ULONG Flags,
  598. // IN ULONG SingleFlag
  599. // );
  600. //
  601. // VOID
  602. // ClearFlag (
  603. // IN ULONG Flags,
  604. // IN ULONG SingleFlag
  605. // );
  606. //
  607. //#ifndef BooleanFlagOn
  608. //#define BooleanFlagOn(F,SF) ( \
  609. // (BOOLEAN)(((F) & (SF)) != 0) \
  610. //)
  611. //#endif
  612. //#ifndef SetFlag
  613. //#define SetFlag(Flags,SingleFlag) { \
  614. // (Flags) |= (SingleFlag); \
  615. //}
  616. //#endif
  617. //#ifndef ClearFlag
  618. //#define ClearFlag(Flags,SingleFlag) { \
  619. // (Flags) &= ~(SingleFlag); \
  620. //}
  621. //#endif
  622. //
  623. // This macro takes a pointer (or ulong) and returns its rounded up word
  624. // value
  625. //
  626. #define WordAlign(Ptr) ( \
  627. ((((ULONG)(Ptr)) + 1) & 0xfffffffe) \
  628. )
  629. //
  630. // This macro takes a pointer (or ulong) and returns its rounded up longword
  631. // value
  632. //
  633. #define LongAlign(Ptr) ( \
  634. ((((ULONG)(Ptr)) + 3) & 0xfffffffc) \
  635. )
  636. //
  637. // This macro takes a pointer (or ulong) and returns its rounded up quadword
  638. // value
  639. //
  640. #define QuadAlign(Ptr) ( \
  641. ((((ULONG)(Ptr)) + 7) & 0xfffffff8) \
  642. )
  643. //
  644. // This macro will up a 64 bit value to the next quad align boundary.
  645. //
  646. #define LiQuadAlign(LI,OUT) { \
  647. *(OUT) = /*xxAdd*/( (LI) + 7 ); \
  648. *((PULONG)(OUT)) &= 0xfffffff8; \
  649. }
  650. //
  651. // CAST
  652. // Add2Ptr (
  653. // IN PVOID Pointer,
  654. // IN ULONG Increment
  655. // IN (CAST)
  656. // );
  657. //
  658. // ULONG
  659. // PtrOffset (
  660. // IN PVOID BasePtr,
  661. // IN PVOID OffsetPtr
  662. // );
  663. //
  664. #define Add2Ptr(PTR,INC,CAST) ((CAST)((PUCHAR)(PTR) + (INC)))
  665. #define PtrOffset(BASE,OFFSET) ((ULONG)((ULONG_PTR)(OFFSET) - (ULONG_PTR)(BASE)))
  666. //
  667. // The following macros are used to establish the semantics needed
  668. // to do a return from within a try-finally clause. As a rule every
  669. // try clause must end with a label call try_exit. For example,
  670. //
  671. // try {
  672. // :
  673. // :
  674. //
  675. // try_exit: NOTHING;
  676. // } finally {
  677. //
  678. // :
  679. // :
  680. // }
  681. //
  682. // Every return statement executed inside of a try clause should use the
  683. // try_return macro. If the compiler fully supports the try-finally construct
  684. // then the macro should be
  685. //
  686. // #define try_return(S) { return(S); }
  687. //
  688. // If the compiler does not support the try-finally construct then the macro
  689. // should be
  690. //
  691. // #define try_return(S) { S; goto try_exit; }
  692. //
  693. #define try_return(S) { S; goto try_exit; }
  694. #endif // _LFSPROCS_