Leaked source code of windows server 2003
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.

1655 lines
56 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. srvmacro.h
  5. Abstract:
  6. This module defines miscellaneous macros for the LAN Manager server.
  7. Author:
  8. Chuck Lenzmeier (chuckl) 2-Mar-90
  9. Revision History:
  10. 19-Nov-1990 mannyw
  11. --*/
  12. #ifndef _SRVMACRO_
  13. #define _SRVMACRO_
  14. #include <limits.h>
  15. //
  16. // For WMI logging
  17. //
  18. extern TRACEHANDLE LoggerHandle;
  19. extern ULONG SrvWmiEnableLevel;
  20. extern ULONG SrvWmiEnableFlags;
  21. #define WPP_GET_LOGGER LoggerHandle
  22. #define SRV_WMI_LEVEL( LVL ) (SrvWmiEnableLevel >= SRV_WMI_LEVEL_ ## LVL )
  23. #define SRV_WMI_FLAGON( FLG ) (SrvWmiEnableFlags & SRV_WMI_FLAG_ ## FLG )
  24. #define SRV_WMI_LEVEL_ALWAYS 0
  25. #define SRV_WMI_LEVEL_SPARSE 1
  26. #define SRV_WMI_LEVEL_VERBOSE 2
  27. #define SRV_WMI_LEVEL_COMPLETE 3
  28. #define SRV_WMI_FLAG_CAPACITY 0x00000000 // Capacity Planning Instrumentation is on if no flag is specified
  29. #define SRV_WMI_FLAG_ERRORS 0x00000001 // Error Tracking Instrumentation
  30. #define SRV_WMI_FLAG_STRESS 0x00000002 // Tracking for IOStress Servers
  31. #define SRV_WMI_FLAG_SYSCACHE 0x00000004 // Tracking for Syscache
  32. //
  33. // Simple MIN and MAX macros. Watch out for side effects!
  34. //
  35. #define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
  36. #define MAX(a,b) ( ((a) < (b)) ? (b) : (a) )
  37. #define RNDM_CONSTANT 314159269 /* default scrambling constant */
  38. #define RNDM_PRIME 1000000007 /* prime number for scrambling */
  39. //
  40. // Used for time conversions
  41. //
  42. #define AlmostTwoSeconds ((2*1000*1000*10)-1)
  43. //
  44. // Used for eventlog throttling
  45. //
  46. #define SRV_ONE_DAY ((LONGLONG)(10*1000*1000)*60*60*24)
  47. //
  48. // Width-agnostic inline to take the difference (in bytes) of two pointer
  49. // values.
  50. //
  51. ULONG_PTR
  52. __inline
  53. PTR_DIFF_FULLPTR(
  54. IN PVOID Ptr1,
  55. IN PVOID Ptr2
  56. )
  57. {
  58. ULONG_PTR difference;
  59. difference = (ULONG_PTR)Ptr1 - (ULONG_PTR)Ptr2;
  60. return difference;
  61. }
  62. ULONG
  63. __inline
  64. PTR_DIFF(
  65. IN PVOID Ptr1,
  66. IN PVOID Ptr2
  67. )
  68. {
  69. ULONG_PTR difference;
  70. difference = (ULONG_PTR)Ptr1 - (ULONG_PTR)Ptr2;
  71. ASSERT( difference < ULONG_MAX );
  72. return (ULONG)difference;
  73. }
  74. USHORT
  75. __inline
  76. PTR_DIFF_SHORT(
  77. IN PVOID Ptr1,
  78. IN PVOID Ptr2
  79. )
  80. {
  81. ULONG difference;
  82. difference = PTR_DIFF(Ptr1, Ptr2);
  83. ASSERT( difference < USHRT_MAX );
  84. return (USHORT)difference;
  85. }
  86. //
  87. // Compute a string hash value that is invariant to case
  88. //
  89. #define COMPUTE_STRING_HASH( _pus, _phash ) { \
  90. PWCHAR _p = (_pus)->Buffer; \
  91. PWCHAR _ep = _p + ((_pus)->Length/sizeof(WCHAR)); \
  92. ULONG _chHolder =0; \
  93. DWORD _ch; \
  94. \
  95. while( _p < _ep ) { \
  96. _ch = RtlUpcaseUnicodeChar( *_p++ ); \
  97. _chHolder = 37 * _chHolder + (unsigned int) _ch ; \
  98. } \
  99. \
  100. *(_phash) = abs(RNDM_CONSTANT * _chHolder) % RNDM_PRIME; \
  101. }
  102. //
  103. // Convert the output of one of the above hash functions to an index into
  104. // a hash table
  105. //
  106. #define HASH_TO_MFCB_INDEX( _hash ) ((_hash) % NMFCB_HASH_TABLE)
  107. #define HASH_TO_SHARE_INDEX( _hash ) ((_hash) % NSHARE_HASH_TABLE)
  108. //
  109. // GET_SERVER_TIME retrieves the server's concept of the current system time.
  110. //
  111. #define GET_SERVER_TIME(_queue, a) (*(a) = (_queue)->stats.SystemTime)
  112. //
  113. // SET_SERVER_TIME updates the server's concept of the current system time.
  114. //
  115. #define SET_SERVER_TIME( _queue ) { \
  116. LARGE_INTEGER currentTime; \
  117. KeQueryTickCount( &currentTime ); \
  118. (_queue)->stats.SystemTime = currentTime.LowPart; \
  119. }
  120. //++
  121. //
  122. // NTSTATUS
  123. // IMPERSONATE (
  124. // IN PWORK_CONTEXT WorkContext
  125. // )
  126. //
  127. // Routine Description:
  128. //
  129. // This macro calls NtSetInformationThread to impersonate a client.
  130. // This should be called before attempting any open on behalf of
  131. // a remote client.
  132. //
  133. // Arguments:
  134. //
  135. // WorkContext - a pointer to a work context block. It must have
  136. // a valid, referenced session pointer, from which the token
  137. // handle is obtained.
  138. //
  139. // Return Value:
  140. //
  141. // None.
  142. //
  143. //--
  144. #define IMPERSONATE( WorkContext ) SrvImpersonate( WorkContext )
  145. //++
  146. //
  147. // VOID
  148. // REVERT (
  149. // IN PWORK_CONTEXT WorkContext
  150. // )
  151. //
  152. // Routine Description:
  153. //
  154. // This macro calls NtSetInformationThread with a NULL token in order
  155. // to revert to a thread's original context. This should be called
  156. // after the IMPERSONATE macro and an open attempt.
  157. //
  158. // Arguments:
  159. //
  160. // None.
  161. //
  162. // Return Value:
  163. //
  164. // None.
  165. //
  166. //--
  167. #define REVERT( ) SrvRevert( )
  168. //
  169. // Determine if the security handle has been initialized
  170. //
  171. #define IS_VALID_SECURITY_HANDLE( handle ) ((handle).dwLower || (handle).dwUpper )
  172. //
  173. // Mark this security handle invalid
  174. //
  175. #define INVALIDATE_SECURITY_HANDLE( handle ) (handle).dwLower = (handle).dwUpper = 0
  176. //++
  177. //
  178. // VOID
  179. // CHECK_FUNCTION_ACCESS (
  180. // IN ACCESS_MASK GrantedAccess,
  181. // IN UCHAR MajorFunction,
  182. // IN UCHAR MinorFunction,
  183. // IN ULONG IoControlCode,
  184. // OUT PNTSTATUS Status
  185. // )
  186. //
  187. // Routine Description:
  188. //
  189. // This macro calls IoCheckFunctionAccess the check the client's
  190. // access to an I/O function identified by major and minor function
  191. // codes.
  192. //
  193. // *** This macro is here only because CHECK_FILE_INFORMATION_ACCESS
  194. // and CHECK_FS_INFORMATION_ACCESS are here.
  195. //
  196. // Arguments:
  197. //
  198. // GrantedAccess - The access granted to the client for the target
  199. // target file object.
  200. //
  201. // MajorFunction - The major function code of the requested
  202. // operation.
  203. //
  204. // MinorFunction - The minor function code of the requested
  205. // operation.
  206. //
  207. // IoControlCode - The control code for device or file system control.
  208. //
  209. // Status - Indicates whether the client has the requested access.
  210. //
  211. // Return Value:
  212. //
  213. // None.
  214. //
  215. //--
  216. #define CHECK_FUNCTION_ACCESS( GrantedAccess, MajorFunction, MinorFunction, \
  217. IoControlCode, Status ) { \
  218. *(Status) = IoCheckFunctionAccess( \
  219. (GrantedAccess), \
  220. (MajorFunction), \
  221. (MinorFunction), \
  222. IoControlCode, \
  223. NULL, \
  224. NULL \
  225. ); \
  226. }
  227. //++
  228. //
  229. // VOID
  230. // CHECK_PAGING_IO_ACCESS (
  231. // IN PWORK_CONTEXT WorkContext
  232. // IN ACCESS_MASK GrantedAccess,
  233. // OUT PNTSTATUS Status
  234. // )
  235. //
  236. // Routine Description:
  237. //
  238. // This macro checks to see if the client opened the file for execute.
  239. // If so, then we allow the redirector to read the file. If this is
  240. // an NT redirector, it must set the FLAGS2_PAGING_IO bit for access
  241. // to be allowed.
  242. //
  243. // Arguments:
  244. //
  245. // GrantedAccess - The access granted to the client for the target
  246. // target file object.
  247. //
  248. // WorkContext - A pointer to a work context block.
  249. //
  250. // Status - Indicates whether the client has the requested access.
  251. //
  252. // Return Value:
  253. //
  254. // None.
  255. //
  256. //--
  257. #define CHECK_PAGING_IO_ACCESS( WorkContext, GrantedAccess, Status ) { \
  258. \
  259. if ( ((GrantedAccess) & FILE_EXECUTE) && \
  260. ( !IS_NT_DIALECT( WorkContext->Connection->SmbDialect ) || \
  261. WorkContext->RequestHeader->Flags2 & \
  262. SMB_FLAGS2_PAGING_IO ) ) { \
  263. *Status = STATUS_SUCCESS; \
  264. } else { \
  265. *Status = STATUS_ACCESS_DENIED; \
  266. } \
  267. }
  268. //++
  269. //
  270. // VOID
  271. // CHECK_FILE_INFORMATION_ACCESS (
  272. // IN ACCESS_MASK GrantedAccess,
  273. // IN UCHAR MajorFunction,
  274. // IN FILE_INFORMATION_CLASS FileInformationClass
  275. // OUT PNTSTATUS Status
  276. // )
  277. //
  278. // Routine Description:
  279. //
  280. // This macro calls IoCheckFunctionAccess the check the client's
  281. // access to a query or set file information function identified by
  282. // major function code and information class.
  283. //
  284. // *** This macro is here because IoCheckFunctionAccess takes an
  285. // OPTIONAL FileInformationClass argument; this is argument is
  286. // therefore passed by reference. Rather than force the caller
  287. // to allocate local storage so that it can pass a constant by
  288. // reference, we do it in the macro.
  289. //
  290. // Arguments:
  291. //
  292. // GrantedAccess - The access granted to the client for the target
  293. // target file object.
  294. //
  295. // MajorFunction - The major function code of the requested
  296. // operation.
  297. //
  298. // FileInformationClass - The type of file information being queried
  299. // or set.
  300. //
  301. // Status - Indicates whether the client has the requested access.
  302. //
  303. // Return Value:
  304. //
  305. // None.
  306. //
  307. //--
  308. #define CHECK_FILE_INFORMATION_ACCESS( GrantedAccess, MajorFunction, \
  309. FileInformationClass, Status ) { \
  310. FILE_INFORMATION_CLASS fileInfoClass = FileInformationClass; \
  311. *(Status) = IoCheckFunctionAccess( \
  312. (GrantedAccess), \
  313. (MajorFunction), \
  314. 0, \
  315. 0, \
  316. &fileInfoClass, \
  317. NULL \
  318. ); \
  319. }
  320. //++
  321. //
  322. // PCHAR
  323. // END_OF_REQUEST_SMB (
  324. // IN PWORK_CONTEXT WorkContext
  325. // )
  326. //
  327. // Routine Description:
  328. //
  329. // This routine returns the address of the last valid location in
  330. // the request SMB associated with the specified work context
  331. // block.
  332. //
  333. // Arguments:
  334. //
  335. // WorkContext - Pointer to the work context block that owns the
  336. // request SMB.
  337. //
  338. // Return Value:
  339. //
  340. // PCHAR - Address of the last valid location in the request SMB.
  341. //
  342. //--
  343. #define END_OF_REQUEST_SMB( WorkContext ) \
  344. ( (PCHAR)( (WorkContext)->RequestBuffer->Buffer ) + \
  345. (WorkContext)->RequestBuffer->DataLength - 1 )
  346. //++
  347. //
  348. // PCHAR
  349. // END_OF_RESPONSE_BUFFER (
  350. // IN PWORK_CONTEXT WorkContext
  351. // )
  352. //
  353. // Routine Description:
  354. //
  355. // This routine returns the address of the last valid location in
  356. // the response buffer associated with the specified work context
  357. // block.
  358. //
  359. // Arguments:
  360. //
  361. // WorkContext - Pointer to the work context block that owns the
  362. // request SMB.
  363. //
  364. // Return Value:
  365. //
  366. // PCHAR - Address of the last valid location in the request SMB.
  367. //
  368. //--
  369. #define END_OF_RESPONSE_BUFFER( WorkContext ) \
  370. ( (PCHAR)( (WorkContext)->ResponseBuffer->Buffer ) + \
  371. (WorkContext)->RequestBuffer->BufferLength - 1 )
  372. //++
  373. //
  374. // PCHAR
  375. // END_OF_TRANSACTION_PARAMETERS (
  376. // IN PTRANSACTION Transaction
  377. // )
  378. //
  379. // Routine Description:
  380. //
  381. // This routine returns the address of the last valid location in
  382. // the InParameters buffer of the transaction block.
  383. //
  384. // Arguments:
  385. //
  386. // Transaction - a pointer to the transaction block to check.
  387. //
  388. // Return Value:
  389. //
  390. // PCHAR - Address of the last valid location in the InParameters
  391. // buffer of the transaction.
  392. //
  393. //--
  394. #define END_OF_TRANSACTION_PARAMETERS( Transaction ) \
  395. ( (PCHAR)( (Transaction)->InParameters ) + \
  396. (Transaction)->ParameterCount - 1 )
  397. //++
  398. //
  399. // VOID
  400. // INTERNAL_ERROR (
  401. // IN ULONG ErrorLevel,
  402. // IN PSZ Message,
  403. // IN PVOID Arg1 OPTIONAL,
  404. // IN PVOID Arg2 OPTIONAL
  405. // )
  406. //
  407. // Routine Description:
  408. //
  409. // This routine handles logging of a server internal error.
  410. //
  411. // *** This macro must be usable in the FSD, at DPC level.
  412. //
  413. // Arguments:
  414. //
  415. // ErrorLevel - The severity of the error
  416. //
  417. // Message - An error message string in DbgPrint() format
  418. //
  419. // Arg1 - Argument 1 for the error message
  420. //
  421. // Arg2 - Argument 2 for the error message
  422. //
  423. //--
  424. #define INTERNAL_ERROR( _level, _msg, _arg1, _arg2 ) { \
  425. IF_DEBUG(ERRORS) { \
  426. DbgPrint( (_msg), (_arg1), (_arg2) ); \
  427. DbgPrint( "\n" ); \
  428. if ( (_level) >= ERROR_LEVEL_UNEXPECTED ) { \
  429. IF_DEBUG(STOP_ON_ERRORS) { \
  430. DbgBreakPoint(); \
  431. } \
  432. } \
  433. } \
  434. if ( (_level) == ERROR_LEVEL_EXPECTED ) { \
  435. ; \
  436. } else if ( (_level) == ERROR_LEVEL_UNEXPECTED ) { \
  437. SrvStatistics.SystemErrors++; \
  438. } else { \
  439. ASSERT( (_level) > ERROR_LEVEL_UNEXPECTED ); \
  440. KeBugCheckEx( \
  441. LM_SERVER_INTERNAL_ERROR, \
  442. BugCheckFileId | __LINE__, \
  443. (ULONG_PTR)(_arg1), \
  444. (ULONG_PTR)(_arg2), \
  445. 0 \
  446. ); \
  447. } \
  448. }
  449. #define SRV_FILE_ACCESS 0x00010000
  450. #define SRV_FILE_BLKCOMM 0x00020000
  451. #define SRV_FILE_BLKCONN 0x00030000
  452. #define SRV_FILE_BLKDEBUG 0x00040000
  453. #define SRV_FILE_BLKENDP 0x00050000
  454. #define SRV_FILE_BLKFILE 0x00060000
  455. #define SRV_FILE_BLKSESS 0x00070000
  456. #define SRV_FILE_BLKSHARE 0x00080000
  457. #define SRV_FILE_BLKSRCH 0x00090000
  458. #define SRV_FILE_BLKTABLE 0x000A0000
  459. #define SRV_FILE_BLKTRANS 0x000B0000
  460. #define SRV_FILE_BLKTREE 0x000C0000
  461. #define SRV_FILE_BLKWORK 0x000D0000
  462. #define SRV_FILE_COPY 0x000E0000
  463. #define SRV_FILE_EA 0x000F0000
  464. #define SRV_FILE_ERRORLOG 0x00100000
  465. #define SRV_FILE_FSD 0x00110000
  466. #define SRV_FILE_FSDDISP 0x00120000
  467. #define SRV_FILE_FSDRAW 0x00130000
  468. #define SRV_FILE_FSDSMB 0x00140000
  469. #define SRV_FILE_FSPINIT 0x00150000
  470. #define SRV_FILE_HEAPMGR 0x00160000
  471. #define SRV_FILE_INFO 0x00170000
  472. #define SRV_FILE_IPX 0x00180000
  473. #define SRV_FILE_IO 0x00190000
  474. #define SRV_FILE_LOCK 0x001A0000
  475. #define SRV_FILE_LOCKCODE 0x001B0000
  476. #define SRV_FILE_MOVE 0x001C0000
  477. #define SRV_FILE_NETWORK 0x001D0000
  478. #define SRV_FILE_OPEN 0x001E0000
  479. #define SRV_FILE_OPLOCK 0x001F0000
  480. #define SRV_FILE_PIPE 0x00200000
  481. #define SRV_FILE_PRNSUPP 0x00210000
  482. #define SRV_FILE_SCAVENGR 0x00220000
  483. #define SRV_FILE_SHARE 0x00230000
  484. #define SRV_FILE_SLMCHECK 0x00240000
  485. #define SRV_FILE_SMBADMIN 0x00250000
  486. #define SRV_FILE_SMBATTR 0x00260000
  487. #define SRV_FILE_SMBCLOSE 0x00270000
  488. #define SRV_FILE_SMBDIR 0x00280000
  489. #define SRV_FILE_SMBFILE 0x00290000
  490. #define SRV_FILE_SMBFIND 0x002A0000
  491. #define SRV_FILE_SMBIOCTL 0x002B0000
  492. #define SRV_FILE_SMBLOCK 0x002C0000
  493. #define SRV_FILE_SMBMISC 0x002D0000
  494. #define SRV_FILE_SMBMPX 0x002E0000
  495. #define SRV_FILE_SMBNOTFY 0x002F0000
  496. #define SRV_FILE_SMBOPEN 0x00300000
  497. #define SRV_FILE_SMBPRINT 0x00310000
  498. #define SRV_FILE_SMBPROC 0x00320000
  499. #define SRV_FILE_SMBRAW 0x00330000
  500. #define SRV_FILE_SMBRDWRT 0x00340000
  501. #define SRV_FILE_SMBSRCH 0x00350000
  502. #define SRV_FILE_SMBSUPP 0x00360000
  503. #define SRV_FILE_SMBTRANS 0x00370000
  504. #define SRV_FILE_SMBTREE 0x00380000
  505. #define SRV_FILE_SRVCONFG 0x00390000
  506. #define SRV_FILE_SRVDATA 0x003A0000
  507. #define SRV_FILE_SRVSTAT 0x003B0000
  508. #define SRV_FILE_SRVSTRNG 0x003C0000
  509. #define SRV_FILE_SVCCDEV 0x003D0000
  510. #define SRV_FILE_SVCCDEVQ 0x003E0000
  511. #define SRV_FILE_SVCCONN 0x003F0000
  512. #define SRV_FILE_SVCFILE 0x00400000
  513. #define SRV_FILE_SVCSESS 0x00410000
  514. #define SRV_FILE_SVCSHARE 0x00420000
  515. #define SRV_FILE_SVCSRV 0x00430000
  516. #define SRV_FILE_SVCSTATS 0x00440000
  517. #define SRV_FILE_SVCSUPP 0x00450000
  518. #define SRV_FILE_SVCXPORT 0x00460000
  519. #define SRV_FILE_WORKER 0x00470000
  520. #define SRV_FILE_XSSUPP 0x00480000
  521. #define SRV_FILE_BLKDIR 0x00490000
  522. #define SRV_FILE_DFS 0x004A0000
  523. //
  524. // Error levels used with INTERNAL_ERROR
  525. //
  526. #define ERROR_LEVEL_EXPECTED 0
  527. #define ERROR_LEVEL_UNEXPECTED 1
  528. #define ERROR_LEVEL_IMPOSSIBLE 2
  529. #define ERROR_LEVEL_FATAL 3
  530. //
  531. // Helper macros for dealing with unqiue identifiers (UID, PID, TID,
  532. // FID, SID). In these macros, id, index, and sequence should all be
  533. // USHORTs.
  534. //
  535. #define TID_INDEX(id) (USHORT)( (id) & 0x07FF )
  536. #define TID_SEQUENCE(id) (USHORT)( (id) >> 11 )
  537. #define MAKE_TID(index, sequence) (USHORT)( ((sequence) << 11) | (index) )
  538. #define INCREMENT_TID_SEQUENCE(id) (id) = (USHORT)(( (id) + 1 ) & 0x1F);
  539. #define UID_INDEX(id) (USHORT)( (id) & 0x07FF )
  540. #define UID_SEQUENCE(id) (USHORT)( (id) >> 11 )
  541. #define MAKE_UID(index, sequence) (USHORT)(( (sequence) << 11) | (index) )
  542. #define INCREMENT_UID_SEQUENCE(id) (id) = (USHORT)(( (id) + 1 ) & 0x1F);
  543. #define FID_INDEX(id) (USHORT)( (id) & 0x03FFF )
  544. #define FID_SEQUENCE(id) (USHORT)( (id) >> 14 )
  545. #define MAKE_FID(index, sequence) (USHORT)( ((sequence) << 14) | (index) )
  546. #define INCREMENT_FID_SEQUENCE(id) (id) = (USHORT)(( (id) + 1 ) & 0x3);
  547. //
  548. // *** Note that the macros relating to search IDs are somewhat
  549. // different from those for other kinds of IDs. The SID is stored
  550. // in a Resume Key (see smb.h for its definition), in discontiguous
  551. // fields. The macros for getting the SID therefore take a pointer
  552. // to a resume key.
  553. //
  554. #define SID_INDEX(ResumeKey) \
  555. (USHORT)( ( ((ResumeKey)->Reserved & 0x7) << 8 ) | \
  556. (ResumeKey)->Sid )
  557. #define SID_SEQUENCE(ResumeKey) \
  558. (USHORT)( ((ResumeKey)->Reserved & 0x18) >> 3 )
  559. #define SID(ResumeKey) \
  560. (USHORT)( ( ((ResumeKey)->Reserved & 0x1F) << 8 ) | \
  561. (ResumeKey)->Sid )
  562. #define INCREMENT_SID_SEQUENCE(id) (id) = (USHORT)(( (id) + 1 ) & 0x3);
  563. #define SET_RESUME_KEY_SEQUENCE(ResumeKey,Sequence) { \
  564. (ResumeKey)->Reserved &= ~0x18; \
  565. (ResumeKey)->Reserved |= (Sequence) << 3; \
  566. }
  567. #define SET_RESUME_KEY_INDEX(ResumeKey,Index) { \
  568. (ResumeKey)->Reserved = (UCHAR)( (ULONG)(Index) >> 8 ); \
  569. (ResumeKey)->Reserved &= (UCHAR)0x7; \
  570. (ResumeKey)->Sid = (UCHAR)( (Index) & (USHORT)0xFF ); \
  571. }
  572. //
  573. // The following SID macros are used in the same way as the macros for
  574. // other IDs (see above, TID, FID, UID). The Find2 protocols (Transaction2)
  575. // use a USHORT as a SID, rather than various fields in a resume key.
  576. //
  577. #define SID_INDEX2(Sid) \
  578. (USHORT)( (Sid) & 0x7FF )
  579. #define SID_SEQUENCE2(Sid) \
  580. (USHORT)( ((Sid) & 0x1800) >> 11 )
  581. #define MAKE_SID(Index,Sequence) \
  582. (USHORT)( ((Sequence) << 11) | (Index) )
  583. //
  584. // InitializeObjectAttributes, with security.
  585. //
  586. #define SrvInitializeObjectAttributes(ObjectAttributes,p1,p2,p3,p4) \
  587. InitializeObjectAttributes(ObjectAttributes,p1,p2,p3,p4); \
  588. (ObjectAttributes)->SecurityQualityOfService = (PVOID)&SrvSecurityQOS;
  589. #define SrvInitializeObjectAttributes_U(ObjectAttributes,p1,p2,p3,p4) \
  590. InitializeObjectAttributes(ObjectAttributes,p1,p2,p3,p4); \
  591. (ObjectAttributes)->SecurityQualityOfService = (PVOID)&SrvSecurityQOS;
  592. //
  593. // Macro used to map from NT attributes to SMB attributes. The output is placed
  594. // in *_SmbAttributes
  595. //
  596. #define SRV_NT_ATTRIBUTES_TO_SMB( _NtAttributes, _Directory, _SmbAttributes ) {\
  597. *(_SmbAttributes) = (USHORT)( (_NtAttributes) & \
  598. ( FILE_ATTRIBUTE_READONLY | \
  599. FILE_ATTRIBUTE_HIDDEN | \
  600. FILE_ATTRIBUTE_SYSTEM | \
  601. FILE_ATTRIBUTE_ARCHIVE | \
  602. FILE_ATTRIBUTE_DIRECTORY )) ; \
  603. if ( _Directory ) { \
  604. *(_SmbAttributes) |= SMB_FILE_ATTRIBUTE_DIRECTORY; \
  605. } \
  606. }
  607. // This macro converts attributes from SMB format to NT format.
  608. //
  609. // The attribute bits in the SMB protocol (same as OS/2) have the
  610. // following meanings:
  611. //
  612. // bit 0 - read only file
  613. // bit 1 - hidden file
  614. // bit 2 - system file
  615. // bit 3 - reserved
  616. // bit 4 - directory
  617. // bit 5 - archive file
  618. //
  619. // NT file attributes are similar, but have a bit set for a "normal"
  620. // file (no other bits set) and do not have a bit set for directories.
  621. // Instead, directory information is passed to and from APIs as a
  622. // BOOLEAN parameter.
  623. #define SRV_SMB_ATTRIBUTES_TO_NT( _SmbAttributes, _Directory, _NtAttributes ) {\
  624. ULONG _attr = (_SmbAttributes); \
  625. *(_NtAttributes) = _attr & \
  626. ( SMB_FILE_ATTRIBUTE_READONLY | \
  627. SMB_FILE_ATTRIBUTE_HIDDEN | \
  628. SMB_FILE_ATTRIBUTE_SYSTEM | \
  629. SMB_FILE_ATTRIBUTE_ARCHIVE | \
  630. SMB_FILE_ATTRIBUTE_DIRECTORY ); \
  631. if ( _attr == 0 ) { \
  632. *(_NtAttributes) = FILE_ATTRIBUTE_NORMAL; \
  633. } \
  634. if( _Directory ) { \
  635. if ( (_attr & SMB_FILE_ATTRIBUTE_DIRECTORY) != 0 ) { \
  636. *(PBOOLEAN)(_Directory) = TRUE; \
  637. } else { \
  638. *(PBOOLEAN)(_Directory) = FALSE; \
  639. } \
  640. } \
  641. }
  642. //
  643. // ULONG
  644. // MAP_SMB_INFO_TYPE_TO_NT (
  645. // IN PULONG Map,
  646. // IN ULONG SmbInformationLevel
  647. // )
  648. //
  649. // Routine description:
  650. //
  651. // This macro maps SMB_INFO level to Nt info level.
  652. //
  653. // Arguments:
  654. //
  655. // Map - An array of ULONGS. The first ulong is the base SMB info level
  656. // the seconds through Nth are NT mappings of the corresponding
  657. // SMB info levels.
  658. //
  659. // Level - The SMB info level to map.
  660. //
  661. // Return Value:
  662. //
  663. // NtInfoLevel - The NT info level.
  664. //
  665. #define MAP_SMB_INFO_TYPE_TO_NT( Map, Level ) Map[Level - Map[0] + 1]
  666. //
  667. // ULONG
  668. // MAP_SMB_INFO_TO_MIN_NT_SIZE (
  669. // IN PULONG Map,
  670. // IN ULONG SmbINformationLevel
  671. // )
  672. //
  673. // Routine Description:
  674. //
  675. // This macro maps SMB_INFO level to the minimum buffer size needed to make the
  676. // NtQueryInformationFile call
  677. //
  678. // Arguments:
  679. // Map - An array of ULONGS. The first ulong is the base SMB info level,
  680. // the second is the NT info level, and the third through Nth are the
  681. // NT mapings for the sizes of the NT info levels.
  682. //
  683. // Level - The SMB info level to find the buffer size
  684. //
  685. // Return Value:
  686. //
  687. // NtMinumumBufferSIze - the minumum buffer size for the request
  688. #define MAP_SMB_INFO_TO_MIN_NT_SIZE( Map, Level ) Map[ Level - Map[0] + 2]
  689. //
  690. // BOOLEAN
  691. // SMB_IS_UNICODE(
  692. // IN PWORK_CONTEXT WorkContext
  693. // )
  694. //
  695. // Routine description:
  696. //
  697. // This macro discovers whether or not an SMB contains Unicode
  698. // ANSI strings.
  699. //
  700. // Arguments:
  701. //
  702. // WorkContext - A pointer to the active work context
  703. //
  704. // Return Value:
  705. //
  706. // TRUE - The SMB strings are unicode.
  707. // FALSE - The SMB strings are ANSI.
  708. //
  709. #define SMB_IS_UNICODE( WorkContext ) \
  710. (BOOLEAN)( ((WorkContext)->RequestHeader->Flags2 & SMB_FLAGS2_UNICODE ) != 0 )
  711. //
  712. // BOOLEAN
  713. // SMB_CONTAINS_DFS_NAME(
  714. // IN PWORK_CONTEXT WorkContext
  715. // )
  716. //
  717. // Routine description:
  718. //
  719. // This macro discovers whether or not an SMB contains a pathname
  720. // referring to the DFS namespace.
  721. //
  722. // Arguments:
  723. //
  724. // WorkContext - A pointer to the active work context
  725. //
  726. // Return Value:
  727. //
  728. // TRUE - The SMB has a DFS name in it
  729. // FALSE - The SMB does not have a DFS name in it
  730. //
  731. #define SMB_CONTAINS_DFS_NAME( WorkContext ) \
  732. (BOOLEAN)( ((WorkContext)->RequestHeader->Flags2 & SMB_FLAGS2_DFS ) != 0 )
  733. //
  734. // BOOLEAN
  735. // SMB_MARK_AS_DFS_NAME(
  736. // IN PWORK_CONTEXT WorkContext
  737. // )
  738. //
  739. // Routine description:
  740. //
  741. // This macro marks the WorkContext as containing a Dfs name. This is
  742. // used when processing SMBs that contain two path names; after the first
  743. // path name has been canonicalized, the SMB is marked as being
  744. // Dfs-Translated by SrvCanonicalizePathName, so the attempt to
  745. // canonicalize the second path in the SMB will fail to do the
  746. // Dfs translation. Calling this macro will ensure that the next call
  747. // to SrvCanonicalizePathName will go through Dfs translation
  748. //
  749. // Arguments:
  750. //
  751. // WorkContext - A pointer to the active work context
  752. //
  753. // Return Value:
  754. //
  755. // None
  756. //
  757. #define SMB_MARK_AS_DFS_NAME( WorkContext ) \
  758. (WorkContext)->RequestHeader->Flags2 |= SMB_FLAGS2_DFS
  759. //
  760. // BOOLEAN
  761. // SMB_MARK_AS_DFS_TRANSLATED(
  762. // IN PWORK_CONTEXT WorkContext
  763. // )
  764. //
  765. // Routine description:
  766. //
  767. // This macro marks the WorkContext as having been through a Dfs
  768. // translation for the express purpose of preventing a second attempt
  769. // at Dfs translation on the translated name.
  770. //
  771. // Arguments:
  772. //
  773. // WorkContext - A pointer to the active work context
  774. //
  775. // Return Value:
  776. //
  777. // None
  778. //
  779. #define SMB_MARK_AS_DFS_TRANSLATED( WorkContext ) \
  780. (WorkContext)->RequestHeader->Flags2 &= (~SMB_FLAGS2_DFS)
  781. //
  782. // BOOLEAN
  783. // CLIENT_CAPABLE_OF(
  784. // IN ULONG Capability,
  785. // IN PCONNECTION Connection
  786. // )
  787. //
  788. // Routine description:
  789. //
  790. // This macro discovers whether or not a client is supports a
  791. // certain capability.
  792. //
  793. // *Warning* This macro assumes that only one capability is being tested.
  794. //
  795. // Arguments:
  796. //
  797. // Connection - A pointer to the active connection
  798. //
  799. // Return Value:
  800. //
  801. // TRUE - Capability supported.
  802. // FALSE - otherwise.
  803. //
  804. #define CLIENT_CAPABLE_OF( Capability, Connection ) \
  805. (BOOLEAN) ( ((Connection)->ClientCapabilities & (CAP_ ## Capability)) != 0 )
  806. //
  807. // BOOLEAN
  808. // SMB_IS_PIPE_PREFIX(
  809. // IN PWORK_CONTEXT WorkContext
  810. // IN PVOID Name
  811. // )
  812. //
  813. // Routine description:
  814. //
  815. // This macro discovers whether or not a path prefix is named pipe prefix
  816. // for a transaction SMB.
  817. //
  818. // Arguments:
  819. //
  820. // WorkContext - A pointer to the active work context
  821. // Name - A pointer to a name string. This may be ANSI or Unicode
  822. //
  823. // Return Value:
  824. //
  825. // TRUE - The name is a pipe prefix.
  826. // FALSE - The name is not a pipe prefix.
  827. //
  828. #define SMB_NAME_IS_PIPE_PREFIX( WorkContext, Name ) \
  829. \
  830. ( ( !SMB_IS_UNICODE( WorkContext ) && \
  831. strnicmp( \
  832. (PCHAR)Name, \
  833. SMB_PIPE_PREFIX, \
  834. SMB_PIPE_PREFIX_LENGTH \
  835. ) == 0 \
  836. ) \
  837. || \
  838. ( SMB_IS_UNICODE( WorkContext ) && \
  839. wcsnicmp( \
  840. (PWCH)Name, \
  841. UNICODE_SMB_PIPE_PREFIX, \
  842. UNICODE_SMB_PIPE_PREFIX_LENGTH / sizeof(WCHAR) \
  843. ) == 0 \
  844. ) \
  845. )
  846. //
  847. // BOOLEAN
  848. // SMB_IS_PIPE_API(
  849. // IN PWORK_CONTEXT WorkContext
  850. // IN PVOID Name
  851. // )
  852. //
  853. // Routine description:
  854. //
  855. // This macro discovers whether or not a transaction name indicates
  856. // that the transaction is for a LM remote API request.
  857. //
  858. // Arguments:
  859. //
  860. // WorkContext - A pointer to the active work context
  861. // Name - A pointer to a name string. This may be ANSI or Unicode
  862. //
  863. // Return Value:
  864. //
  865. // TRUE - The name is a remote API request.
  866. // FALSE - The name is not a remote API request.
  867. //
  868. #define SMB_NAME_IS_PIPE_API( WorkContext, Name ) \
  869. \
  870. ( ( !SMB_IS_UNICODE( WorkContext ) && \
  871. stricmp( \
  872. (PCHAR)Name, \
  873. StrPipeApiOem \
  874. ) == 0 \
  875. ) \
  876. || \
  877. ( SMB_IS_UNICODE( WorkContext ) && \
  878. wcsicmp( \
  879. (PWCH)Name, \
  880. StrPipeApi \
  881. ) == 0 \
  882. ) \
  883. )
  884. //
  885. // VOID
  886. // SrvReferenceConnection (
  887. // PCONNECTION Connection
  888. // )
  889. //
  890. // Routine Description:
  891. //
  892. // This macro increments the reference count on a connection block.
  893. //
  894. // !!! Users of this macro must be nonpageable.
  895. //
  896. // Arguments:
  897. //
  898. // Connection - Address of connection
  899. //
  900. // Return Value:
  901. //
  902. // None.
  903. //
  904. #define SrvReferenceConnection( _conn_ ) { \
  905. ASSERT( GET_BLOCK_TYPE(_conn_) == \
  906. BlockTypeConnection ); \
  907. UPDATE_REFERENCE_HISTORY( (_conn_), FALSE ); \
  908. (VOID) ExInterlockedAddUlong( \
  909. &(_conn_)->BlockHeader.ReferenceCount, \
  910. 1, \
  911. (_conn_)->EndpointSpinLock \
  912. ); \
  913. IF_DEBUG(REFCNT) { \
  914. SrvHPrint2( \
  915. "Referencing connection %lx; new refcnt %lx\n", \
  916. (_conn_), (_conn_)->BlockHeader.ReferenceCount); \
  917. } \
  918. }
  919. //
  920. // VOID
  921. // SrvReferenceConnectionLocked (
  922. // PCONNECTION Connection
  923. // )
  924. //
  925. // Routine Description:
  926. //
  927. // This macro increments the reference count on a connection block.
  928. // Invokers of this macro must hold the SrvFsdSpinLock.
  929. //
  930. // Arguments:
  931. //
  932. // Connection - Address of connection
  933. //
  934. // Return Value:
  935. //
  936. // None.
  937. //
  938. #define SrvReferenceConnectionLocked( _conn_ ) { \
  939. ASSERT( GET_BLOCK_TYPE(_conn_) == \
  940. BlockTypeConnection ); \
  941. UPDATE_REFERENCE_HISTORY( (_conn_), FALSE ); \
  942. (_conn_)->BlockHeader.ReferenceCount++; \
  943. IF_DEBUG(REFCNT) { \
  944. SrvHPrint2( \
  945. "Referencing connection %lx; new refcnt %lx\n", \
  946. (_conn_), (_conn_)->BlockHeader.ReferenceCount ); \
  947. } \
  948. }
  949. //
  950. // VOID
  951. // SrvReferenceSession (
  952. // PSESSION Session
  953. // )
  954. //
  955. // Routine Description:
  956. //
  957. // This macro increments the reference count on a session block.
  958. //
  959. // Arguments:
  960. //
  961. // Session - Address of session
  962. //
  963. // Return Value:
  964. //
  965. // None.
  966. //
  967. #define SrvReferenceSession( _sess_ ) { \
  968. ASSERT( (_sess_)->NonpagedHeader->ReferenceCount > 0 ); \
  969. ASSERT( GET_BLOCK_TYPE(_sess_) == BlockTypeSession ); \
  970. UPDATE_REFERENCE_HISTORY( (_sess_), FALSE ); \
  971. InterlockedIncrement( \
  972. &(_sess_)->NonpagedHeader->ReferenceCount \
  973. ); \
  974. IF_DEBUG(REFCNT) { \
  975. SrvHPrint2( \
  976. "Referencing session %lx; new refcnt %lx\n", \
  977. (_sess_), (_sess_)->NonpagedHeader->ReferenceCount ); \
  978. } \
  979. }
  980. //
  981. // VOID
  982. // SrvReferenceTransaction (
  983. // PTRANSACTION Transaction
  984. // )
  985. //
  986. // Routine Description:
  987. //
  988. // This macro increments the reference count on a transaction block.
  989. //
  990. // Arguments:
  991. //
  992. // Transaction - Address of transaction
  993. //
  994. // Return Value:
  995. //
  996. // None.
  997. //
  998. #define SrvReferenceTransaction( _trans_ ) { \
  999. ASSERT( (_trans_)->NonpagedHeader->ReferenceCount > 0 ); \
  1000. ASSERT( GET_BLOCK_TYPE(_trans_) == BlockTypeTransaction ); \
  1001. UPDATE_REFERENCE_HISTORY( (_trans_), FALSE ); \
  1002. InterlockedIncrement( \
  1003. &(_trans_)->NonpagedHeader->ReferenceCount \
  1004. ); \
  1005. IF_DEBUG(REFCNT) { \
  1006. SrvHPrint2( \
  1007. "Referencing transaction %lx; new refcnt %lx\n", \
  1008. (_trans_), (_trans_)->NonpagedHeader->ReferenceCount ); \
  1009. } \
  1010. }
  1011. //
  1012. // VOID
  1013. // SrvReferenceTreeConnect (
  1014. // PTREE_CONNECT TreeConnect
  1015. // )
  1016. //
  1017. // Routine Description:
  1018. //
  1019. // This macro increments the reference count on a tree connect block.
  1020. // Invokers of this macro must hold TreeConnect->Connection->Lock.
  1021. //
  1022. // Arguments:
  1023. //
  1024. // TreeConnect - Address of tree connect
  1025. //
  1026. // Return Value:
  1027. //
  1028. // None.
  1029. //
  1030. #define SrvReferenceTreeConnect( _tree_ ) { \
  1031. ASSERT( (_tree_)->NonpagedHeader->ReferenceCount > 0 ); \
  1032. ASSERT( GET_BLOCK_TYPE(_tree_) == BlockTypeTreeConnect ); \
  1033. UPDATE_REFERENCE_HISTORY( (_tree_), FALSE ); \
  1034. InterlockedIncrement( \
  1035. &(_tree_)->NonpagedHeader->ReferenceCount \
  1036. ); \
  1037. IF_DEBUG(REFCNT) { \
  1038. SrvHPrint2( \
  1039. "Referencing tree connect %lx; new refcnt %lx\n", \
  1040. (_tree_), (_tree_)->NonpagedHeader->ReferenceCount ); \
  1041. } \
  1042. }
  1043. //
  1044. // VOID
  1045. // SrvReferenceWorkItem (
  1046. // IN PWORK_CONTEXT WorkContext
  1047. // )
  1048. //
  1049. // Routine Description:
  1050. //
  1051. // This function increments the reference count of a work context block.
  1052. // Invokers of this macro must hold WorkContext->SpinLock.
  1053. //
  1054. // Arguments:
  1055. //
  1056. // WORK_CONTEXT - Pointer to the work context block to reference.
  1057. //
  1058. // Return Value:
  1059. //
  1060. // None.
  1061. //
  1062. #define SrvReferenceWorkItem( _wc_ ) { \
  1063. ASSERT( (LONG)(_wc_)->BlockHeader.ReferenceCount >= 0 ); \
  1064. ASSERT( (GET_BLOCK_TYPE(_wc_) == BlockTypeWorkContextInitial) || \
  1065. (GET_BLOCK_TYPE(_wc_) == BlockTypeWorkContextNormal) || \
  1066. (GET_BLOCK_TYPE(_wc_) == BlockTypeWorkContextRaw) ); \
  1067. UPDATE_REFERENCE_HISTORY( (_wc_), FALSE ); \
  1068. (_wc_)->BlockHeader.ReferenceCount++; \
  1069. IF_DEBUG(REFCNT) { \
  1070. SrvHPrint2( \
  1071. "Referencing WorkContext 0x%lx; new refcnt 0x%lx\n", \
  1072. (_wc_), (_wc_)->BlockHeader.ReferenceCount ); \
  1073. } \
  1074. }
  1075. //
  1076. // VOID
  1077. // SRV_START_SEND (
  1078. // IN OUT PWORK_CONTEXT WorkContext,
  1079. // IN PMDL Mdl OPTIONAL,
  1080. // IN ULONG SendOptions,
  1081. // IN PRESTART_ROUTINE FsdRestartRoutine,
  1082. // IN PRESTART_ROUTINE FspRestartRoutine
  1083. // )
  1084. //
  1085. // Routine Description:
  1086. //
  1087. // This macro calls the SrvStartSend routine. It sets the fsd and
  1088. // fsp restart routines before calling it.
  1089. //
  1090. // Arguments:
  1091. //
  1092. // WorkContext - Supplies a pointer to a Work Context block.
  1093. //
  1094. // Mdl - Supplies a pointer to the first (or only) MDL describing the
  1095. // data that is to be sent.
  1096. //
  1097. // SendOptions - Supplied TDI send options.
  1098. //
  1099. // FsdRestartRoutine - Supplies the address of the FSD routine that is
  1100. // to be called when the I/O completes. (Often, this is
  1101. // SrvQueueWorkToFspAtDpcLevel.)
  1102. //
  1103. // FspRestartRoutine - Supplies the address of the FSP routine that is
  1104. // to be called when the FSD queues the work item to the FSP.
  1105. //
  1106. #define SRV_START_SEND( _wc, _mdl, _opt, _compl, _fsdRestart, _fspRestart ) { \
  1107. ASSERT( !(_wc)->Endpoint->IsConnectionless ); \
  1108. if ( (_fspRestart) != NULL ) { \
  1109. (_wc)->FspRestartRoutine = (_fspRestart); \
  1110. } \
  1111. if ( (_fsdRestart) != NULL ) { \
  1112. (_wc)->FsdRestartRoutine = (_fsdRestart); \
  1113. } \
  1114. SrvStartSend( (_wc), (_compl), (_mdl), (_opt) ); \
  1115. }
  1116. #define SRV_START_SEND_2( _wc, _compl, _fsdRestart, _fspRestart ) { \
  1117. (_wc)->ResponseBuffer->Mdl->ByteCount = \
  1118. (_wc)->ResponseBuffer->DataLength; \
  1119. if ( (_fspRestart) != NULL ) { \
  1120. (_wc)->FspRestartRoutine = (_fspRestart); \
  1121. } \
  1122. if ( (_fsdRestart) != NULL ) { \
  1123. (_wc)->FsdRestartRoutine = (_fsdRestart); \
  1124. } \
  1125. if ( !(_wc)->Endpoint->IsConnectionless ) { \
  1126. SrvStartSend2( (_wc), (_compl) ); \
  1127. } else { \
  1128. SrvIpxStartSend( (_wc), (_compl) ); \
  1129. } \
  1130. }
  1131. //
  1132. // VOID
  1133. // SrvUpdateErrorCount(
  1134. // PSRV_ERROR_RECORD ErrorRecord,
  1135. // BOOLEAN IsError
  1136. // )
  1137. // /*++
  1138. //
  1139. // Routine Description:
  1140. //
  1141. // This routine updates the server's record of successful / unsuccesful
  1142. // operations.
  1143. //
  1144. // Arguments:
  1145. //
  1146. // IsError - TRUE - A server error occured
  1147. // FALSE - A server operation was attempted
  1148. //
  1149. // Return Value:
  1150. //
  1151. // None.
  1152. //
  1153. #if 0
  1154. #define SrvUpdateErrorCount( ErrorRecord, IsError ) \
  1155. if ( IsError ) { \
  1156. (ErrorRecord)->FailedOperations++; \
  1157. } else { \
  1158. (ErrorRecord)->SuccessfulOperations++; \
  1159. }
  1160. #else
  1161. #define SrvUpdateErrorCount( ErrorRecord, IsError )
  1162. #endif
  1163. //
  1164. // VOID
  1165. // SrvUpdateStatistics (
  1166. // PWORK_CONTEXT WorkContext,
  1167. // ULONG BytesSent,
  1168. // UCHAR SmbCommand
  1169. // )
  1170. //
  1171. // Routine Description:
  1172. //
  1173. // Macro to update the server statistics database to reflect the
  1174. // work item that is being completed.
  1175. //
  1176. // Arguments:
  1177. //
  1178. // WorkContext - Pointer to the workcontext block containing
  1179. // the statistics for this request.
  1180. //
  1181. // BytesSent - Supplies a count of the number of bytes of response data
  1182. // sent as a result of the current SMB.
  1183. //
  1184. // SmbCommand - The SMB command code of the current operation.
  1185. //
  1186. //
  1187. // Return Value:
  1188. //
  1189. // None.
  1190. //
  1191. #if SRVDBG_STATS
  1192. VOID SRVFASTCALL
  1193. SrvUpdateStatistics2 (
  1194. PWORK_CONTEXT WorkContext,
  1195. UCHAR SmbCommand
  1196. );
  1197. #define UPDATE_STATISTICS2(_work,_cmd) SrvUpdateStatistics2((_work),(_cmd))
  1198. #else
  1199. #define UPDATE_STATISTICS2(_work,_cmd)
  1200. #endif
  1201. #define UPDATE_STATISTICS(_work,_sent,_cmd ) { \
  1202. _work->CurrentWorkQueue->stats.BytesSent += (_sent); \
  1203. UPDATE_STATISTICS2((_work),(_cmd)); \
  1204. }
  1205. #define UPDATE_READ_STATS( _work, _count) { \
  1206. _work->CurrentWorkQueue->stats.ReadOperations++; \
  1207. _work->CurrentWorkQueue->stats.BytesRead += (_count); \
  1208. }
  1209. #define UPDATE_WRITE_STATS(_work, _count) { \
  1210. _work->CurrentWorkQueue->stats.WriteOperations++; \
  1211. _work->CurrentWorkQueue->stats.BytesWritten += (_count); \
  1212. }
  1213. //
  1214. // VOID
  1215. // SrvFsdSendResponse (
  1216. // IN OUT PWORK_CONTEXT WorkContext
  1217. // )
  1218. //
  1219. // Routine Description:
  1220. //
  1221. // This routine is called when all request processing on an SMB is
  1222. // complete and a response is to be sent. It starts the sending of
  1223. // that response. The work item will be queued for final cleanup when
  1224. // the send completes.
  1225. //
  1226. // Arguments:
  1227. //
  1228. // WorkContext - Supplies a pointer to the work context block
  1229. // containing information about the SMB.
  1230. //
  1231. // Return Value:
  1232. //
  1233. // None.
  1234. //
  1235. #define SrvFsdSendResponse( _wc ) { \
  1236. \
  1237. (_wc)->ResponseBuffer->DataLength = \
  1238. (CLONG)( (PCHAR)(_wc)->ResponseParameters - \
  1239. (PCHAR)(_wc)->ResponseHeader ); \
  1240. (_wc)->ResponseHeader->Flags |= SMB_FLAGS_SERVER_TO_REDIR; \
  1241. SRV_START_SEND_2( (_wc), SrvFsdRestartSmbAtSendCompletion, NULL, NULL ); \
  1242. }
  1243. //
  1244. // VOID
  1245. // SrvFsdSendResponse2 (
  1246. // IN OUT PWORK_CONTEXT WorkContext,
  1247. // IN PRESTART_ROUTINE FspRestartRoutine
  1248. // )
  1249. //
  1250. // Routine Description:
  1251. //
  1252. // This routine is identical to SrvFsdSendResponse, except that
  1253. // processing restarts after the send in the FSP, not the FSD.
  1254. //
  1255. // *** If you change either SrvFsdSendResponse or SrvFsdSendResponse2,
  1256. // CHANGE BOTH OF THEM!
  1257. //
  1258. // Arguments:
  1259. //
  1260. // WorkContext - Supplies a pointer to the work context block
  1261. // containing information about the SMB.
  1262. //
  1263. // FspRestartRoutine - Supplies the address of the restart routine in
  1264. // the FSP that is to be called when the TdiSend completes.
  1265. //
  1266. // Return Value:
  1267. //
  1268. // None.
  1269. //
  1270. #define SrvFsdSendResponse2( _wc, _fspRestart ) { \
  1271. \
  1272. (_wc)->ResponseBuffer->DataLength = \
  1273. (CLONG)( (PCHAR)(_wc)->ResponseParameters - \
  1274. (PCHAR)(_wc)->ResponseHeader ); \
  1275. (_wc)->ResponseHeader->Flags |= SMB_FLAGS_SERVER_TO_REDIR; \
  1276. SRV_START_SEND_2((_wc), SrvQueueWorkToFspAtSendCompletion, NULL, (_fspRestart));\
  1277. }
  1278. //
  1279. // VOID
  1280. // ParseLockData (
  1281. // IN BOOLEAN LargeFileLock,
  1282. // IN PLOCKING_ANDX_RANGE SmallRange,
  1283. // IN PNTLOCKING_ANDX_RANGE LargeRange,
  1284. // OUT PUSHORT Pid,
  1285. // OUT PLARGE_INTEGER Offset,
  1286. // OUT PLARGE_INTEGER Length
  1287. // )
  1288. // {
  1289. //
  1290. #define ParseLockData( _largeLock, _sr, _lr, _pid, _offset, _len ) { \
  1291. \
  1292. if ( _largeLock ) { \
  1293. *(_pid) = SmbGetUshort( &(_lr)->Pid ); \
  1294. (_offset)->LowPart = SmbGetUlong( &(_lr)->OffsetLow ); \
  1295. (_offset)->HighPart = SmbGetUlong( &(_lr)->OffsetHigh ); \
  1296. (_len)->LowPart = SmbGetUlong( &(_lr)->LengthLow ); \
  1297. (_len)->HighPart = SmbGetUlong( &(_lr)->LengthHigh ); \
  1298. } else { \
  1299. *(_pid) = SmbGetUshort( &(_sr)->Pid ); \
  1300. (_offset)->QuadPart = SmbGetUlong( &(_sr)->Offset ); \
  1301. (_len)->QuadPart = SmbGetUlong( &(_sr)->Length ); \
  1302. } \
  1303. }
  1304. //
  1305. // CHECK_SEND_COMPLETION_STATUS( _status ) will log errors
  1306. // that occurs during send completion.
  1307. //
  1308. #define CHECK_SEND_COMPLETION_STATUS( _status ) { \
  1309. InterlockedDecrement( &WorkContext->Connection->OperationsPendingOnTransport ); \
  1310. if ( !NT_SUCCESS( _status ) ) { \
  1311. SrvCheckSendCompletionStatus( _status, __LINE__ ); \
  1312. } else { \
  1313. SrvUpdateErrorCount( &SrvNetworkErrorRecord, FALSE ); \
  1314. } \
  1315. }
  1316. #define CHECK_SEND_COMPLETION_STATUS_CONNECTIONLESS( _status ) { \
  1317. if ( !NT_SUCCESS( _status ) ) { \
  1318. SrvCheckSendCompletionStatus( _status, __LINE__ ); \
  1319. } else { \
  1320. SrvUpdateErrorCount( &SrvNetworkErrorRecord, FALSE ); \
  1321. } \
  1322. }
  1323. //
  1324. // Definitions for unlockable code sections.
  1325. //
  1326. #define SRV_CODE_SECTION_1AS 0
  1327. #define SRV_CODE_SECTION_8FIL 1
  1328. #define SRV_CODE_SECTION_MAX 2
  1329. extern SRV_LOCK SrvUnlockableCodeLock;
  1330. typedef struct _SECTION_DESCRIPTOR {
  1331. PVOID Base;
  1332. PVOID Handle;
  1333. ULONG ReferenceCount;
  1334. } SECTION_DESCRIPTOR, *PSECTION_DESCRIPTOR;
  1335. extern SECTION_DESCRIPTOR SrvSectionInfo[SRV_CODE_SECTION_MAX];
  1336. #define UNLOCKABLE_CODE( _section ) \
  1337. ASSERTMSG( "Unlockable code called while section not locked", \
  1338. SrvSectionInfo[SRV_CODE_SECTION_##_section##].Handle != NULL )
  1339. VOID
  1340. SrvReferenceUnlockableCodeSection (
  1341. IN ULONG CodeSection
  1342. );
  1343. VOID
  1344. SrvDereferenceUnlockableCodeSection (
  1345. IN ULONG CodeSection
  1346. );
  1347. //
  1348. // We only need to lock these sections on the workstation product,
  1349. // since we lock them down in InitializeServer() if we're NTAS
  1350. //
  1351. #define REFERENCE_UNLOCKABLE_CODE( _section ) \
  1352. if( !SrvProductTypeServer ) SrvReferenceUnlockableCodeSection( SRV_CODE_SECTION_##_section## )
  1353. #define DEREFERENCE_UNLOCKABLE_CODE( _section ) \
  1354. if( !SrvProductTypeServer) SrvDereferenceUnlockableCodeSection( SRV_CODE_SECTION_##_section## )
  1355. #define GET_BLOCKING_WORK_QUEUE() ( (SrvNumberOfProcessors < 4) ? SrvBlockingWorkQueues : (SrvBlockingWorkQueues + KeGetCurrentProcessorNumber()) )
  1356. //
  1357. // VOID
  1358. // SrvInsertWorkQueueTail (
  1359. // IN OUT PWORK_QUEUE WorkQueue,
  1360. // IN PQUEUEABLE_BLOCK_HEADER WorkItem
  1361. // )
  1362. #if SRVDBG_STATS2
  1363. #define SrvInsertWorkQueueTail( _workQ, _workItem ) { \
  1364. ULONG depth; \
  1365. GET_SERVER_TIME( _workQ, &(_workItem)->Timestamp ); \
  1366. depth = KeInsertQueue( &(_workQ)->Queue, &(_workItem)->ListEntry ); \
  1367. (_workQ)->ItemsQueued++; \
  1368. if ( (LONG)depth > (_workQ)->MaximumDepth ) { \
  1369. (_workQ)->MaximumDepth = (LONG)depth; \
  1370. } \
  1371. }
  1372. #else
  1373. #define SrvInsertWorkQueueTail( _workQ, _workItem ) { \
  1374. GET_SERVER_TIME( _workQ, &(_workItem)->Timestamp ); \
  1375. (VOID)KeInsertQueue( &(_workQ)->Queue, &(_workItem)->ListEntry ); \
  1376. }
  1377. #endif // SRVDBG_STATS2
  1378. //
  1379. // VOID
  1380. // SrvInsertWorkQueueHead (
  1381. // IN OUT PWORK_QUEUE WorkQueue,
  1382. // IN PQUEUEABLE_BLOCK_HEADER WorkItem
  1383. // )
  1384. #define SrvInsertWorkQueueHead( _workQ, _workItem ) { \
  1385. GET_SERVER_TIME( _workQ, &(_workItem)->Timestamp ); \
  1386. (VOID)KeInsertHeadQueue( &(_workQ)->Queue, &(_workItem)->ListEntry );\
  1387. }
  1388. //
  1389. // BOOLEAN
  1390. // SrvRetryDueToDismount(
  1391. // IN PSHARE Share,
  1392. // IN NTSTATUS Status
  1393. // )
  1394. #define SrvRetryDueToDismount( _share, _status ) \
  1395. ((_status) == STATUS_VOLUME_DISMOUNTED && \
  1396. SrvRefreshShareRootHandle( _share, &(_status) ) )
  1397. #if DBG_STUCK
  1398. #define SET_OPERATION_START_TIME( _context ) \
  1399. if( *(_context) != NULL ) KeQuerySystemTime( &((*(_context))->OpStartTime) );
  1400. #else
  1401. #define SET_OPERATION_START_TIME( _context )
  1402. #endif
  1403. #if DBG
  1404. #define CHECKIRP( irp ) { \
  1405. if( (irp) && (irp)->CurrentLocation != (irp)->StackCount + 1 ) { \
  1406. DbgPrint( "SRV: IRP %p already in use at %u!\n", irp, __LINE__ ); \
  1407. DbgBreakPoint(); \
  1408. } \
  1409. }
  1410. #else
  1411. #define CHECKIRP( irp )
  1412. #endif
  1413. //
  1414. // Allocate a WORK_CONTEXT structure.
  1415. //
  1416. #define INITIALIZE_WORK_CONTEXT( _queue, _context ) {\
  1417. (_context)->BlockHeader.ReferenceCount = 1; \
  1418. GET_SERVER_TIME( _queue, &(_context)->Timestamp ); \
  1419. RtlZeroMemory( &(_context)->Endpoint, sizeof( struct _WorkContextZeroBeforeReuse ) ); \
  1420. SrvWmiInitContext((_context)); \
  1421. }
  1422. #define ALLOCATE_WORK_CONTEXT( _queue, _context ) { \
  1423. *(_context) = NULL; \
  1424. *(_context) = (PWORK_CONTEXT)InterlockedExchangePointer( &(_queue)->FreeContext, (*_context) ); \
  1425. if( *(_context) != NULL ) { \
  1426. INITIALIZE_WORK_CONTEXT( _queue, *(_context) ); \
  1427. } else { \
  1428. *(_context) = SrvFsdGetReceiveWorkItem( _queue ); \
  1429. } \
  1430. CHECKIRP( *(_context) ? (*(_context))->Irp : NULL ); \
  1431. SET_OPERATION_START_TIME( _context ) \
  1432. }
  1433. //
  1434. // Returns the work item to the free list.
  1435. //
  1436. #define RETURN_FREE_WORKITEM( _wc ) \
  1437. do { \
  1438. PWORK_QUEUE _queue = _wc->CurrentWorkQueue; \
  1439. ASSERT( _queue >= SrvWorkQueues && _queue < eSrvWorkQueues ); \
  1440. ASSERT( _wc->BlockHeader.ReferenceCount == 0 ); \
  1441. ASSERT( _wc->FreeList != NULL ); \
  1442. CHECKIRP( (_wc)->Irp ); \
  1443. if( (_wc)->Irp->AssociatedIrp.SystemBuffer && \
  1444. (_wc)->Irp->Flags & IRP_DEALLOCATE_BUFFER ) { \
  1445. ExFreePool( (_wc)->Irp->AssociatedIrp.SystemBuffer ); \
  1446. (_wc)->Irp->AssociatedIrp.SystemBuffer = NULL; \
  1447. (_wc)->Irp->Flags &= ~IRP_DEALLOCATE_BUFFER; \
  1448. } \
  1449. if( _queue->NeedWorkItem ) { \
  1450. if( InterlockedDecrement( &(_queue->NeedWorkItem) ) >= 0 ){ \
  1451. _wc->FspRestartRoutine = SrvServiceWorkItemShortage; \
  1452. SrvInsertWorkQueueHead( _queue, _wc ); \
  1453. break; \
  1454. } else { \
  1455. InterlockedIncrement( &(_queue->NeedWorkItem) ); \
  1456. } \
  1457. } \
  1458. _wc = (PWORK_CONTEXT)InterlockedExchangePointer( &_queue->FreeContext, _wc ); \
  1459. if( _wc ) { \
  1460. CHECKIRP( (_wc)->Irp ); \
  1461. ExInterlockedPushEntrySList( _wc->FreeList, &_wc->SingleListEntry, &_queue->SpinLock );\
  1462. InterlockedIncrement( &_queue->FreeWorkItems ); \
  1463. } \
  1464. } while (0);
  1465. //
  1466. // Our current work queue, based on our current processor
  1467. //
  1468. #if MULTIPROCESSOR
  1469. #define PROCESSOR_TO_QUEUE() (&SrvWorkQueues[ KeGetCurrentProcessorNumber() ])
  1470. #else
  1471. #define PROCESSOR_TO_QUEUE() (&SrvWorkQueues[0])
  1472. #endif
  1473. #define SET_INVALID_CONTEXT_HANDLE(h) ((h).dwLower = (h).dwUpper = (ULONG)(-1))
  1474. #define IS_VALID_CONTEXT_HANDLE(h) (((h).dwLower != (ULONG) -1) && ((h).dwUpper != (ULONG) -1))
  1475. #ifdef POOL_TAGGING
  1476. //
  1477. // Macro to map from block type to pool tag.
  1478. //
  1479. extern ULONG SrvPoolTags[BlockTypeMax-1];
  1480. #define TAG_FROM_TYPE(_type) SrvPoolTags[(_type)-1]
  1481. #else
  1482. #define TAG_FROM_TYPE(_type) ignoreme
  1483. #endif // def POOL_TAGGING
  1484. #endif // def _SRVMACRO_