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.

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