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.

628 lines
19 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. smbce.h
  5. Abstract:
  6. This module defines all functions, along with implementations for inline functions
  7. related to accessing the SMB connection engine
  8. Revision History:
  9. Balan Sethu Raman [SethuR] 6-March-1995
  10. --*/
  11. #ifndef _SMBCE_H_
  12. #define _SMBCE_H_
  13. #define SECURITY_KERNEL
  14. #define SECURITY_NTLM
  15. #include "security.h"
  16. #include "secint.h"
  17. #include "md5.h"
  18. //
  19. // Flag to enable/disable double buffering on exchanges with security signatures.
  20. //
  21. #define SMBCE_NO_DOUBLE_BUFFERING 0x80000000
  22. //
  23. // The SMB protocol has a number of dialects. These reflect the extensions made
  24. // to the core protocol over a period of time to cater to increasingly sophisticated
  25. // file systems. The connection engine must be capable of dealing with different
  26. // dialects implemented by server. The underlying Transport mechanism is used to
  27. // uniquely identify the file server and the SMB protocol furnishes the remaining
  28. // identification information to uniquely map an SMB onto a particular file opened by
  29. // a particular client. The three important pieces of information are the SMB_TREE_ID,
  30. // SMB_FILE_ID and SMB_USER_ID. These identify the particular connection made by a
  31. // client machine, the particular file opened on that connection, and the user on
  32. // behalf of whom the file has been opened. Note that there could be multiple
  33. // connections from a client machine to a server machine. Therefore the unique id. is
  34. // really connection based rather than machine based. The SMB connection engine
  35. // data structures are built around these concepts.
  36. //
  37. // The known SMB dialects are as follows.
  38. //
  39. typedef enum _SMB_DIALECT_ {
  40. PCNET1_DIALECT,
  41. //XENIXCORE_DIALECT,
  42. //MSNET103_DIALECT,
  43. LANMAN10_DIALECT,
  44. WFW10_DIALECT,
  45. LANMAN12_DIALECT,
  46. LANMAN21_DIALECT,
  47. NTLANMAN_DIALECT
  48. } SMB_DIALECT, *PSMB_DIALECT;
  49. #define NET_ROOT_FILESYSTEM_UNKOWN ((UCHAR)0)
  50. #define NET_ROOT_FILESYSTEM_FAT ((UCHAR)1)
  51. #define NET_ROOT_FILESYSTEM_NTFS ((UCHAR)2)
  52. typedef UCHAR NET_ROOT_FILESYSTEM, *PNET_ROOT_FILESYSTEM;
  53. //
  54. // The SMBCE_NET_ROOT encapsulates the information pertaining to a share on a server.
  55. //
  56. //we restrict to the first 7 characters (HPFS386)
  57. #define SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL 7
  58. #define MaximumNumberOfVNetRootContextsForScavenging 10
  59. typedef struct _SMBCE_NET_ROOT_ {
  60. BOOLEAN DfsAware;
  61. NET_ROOT_TYPE NetRootType;
  62. NET_ROOT_FILESYSTEM NetRootFileSystem;
  63. SMB_USER_ID UserId;
  64. ULONG MaximumReadBufferSize;
  65. ULONG MaximumWriteBufferSize;
  66. LIST_ENTRY ClusterSizeSerializationQueue;
  67. ULONG FileSystemAttributes;
  68. LONG MaximumComponentNameLength;
  69. USHORT CompressionFormatAndEngine;
  70. UCHAR CompressionUnitShift;
  71. UCHAR ChunkShift;
  72. UCHAR ClusterShift;
  73. ULONG ChunkSize;
  74. //CSC Stuff
  75. CSC_ROOT_INFO sCscRootInfo;
  76. ULONG CachedNumberOfSrvOpens;
  77. BOOLEAN CscEnabled; //this, if we are to automatically build shadows
  78. BOOLEAN CscShadowable; //this, if we are allowed to build shadows
  79. USHORT CscFlags; // CSC flags as returned by the server
  80. BOOLEAN UpdateCscShareRights; // indication to update share rights on the CSC database
  81. BOOLEAN Disconnected;
  82. LIST_ENTRY DirNotifyList; // head of a list of notify Irps.
  83. PNOTIFY_SYNC pNotifySync; // used to synchronize the dir notify list.
  84. LIST_ENTRY NotifyeeFobxList; // list of fobx's given to the fsrtl structure
  85. FAST_MUTEX NotifyeeFobxListMutex;
  86. union {
  87. struct {
  88. USHORT FileSystemNameLength;
  89. WCHAR FileSystemName[SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL];
  90. };
  91. struct {
  92. USHORT Pad2;
  93. UCHAR FileSystemNameALength;
  94. UCHAR FileSystemNameA[SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL];
  95. UCHAR Pad; //this field is used for a null in a dbgprint; don't move it
  96. };
  97. };
  98. //ULONG ClusterSize;
  99. } SMBCE_NET_ROOT, *PSMBCE_NET_ROOT;
  100. //
  101. // There are two levels of security in the SMB protocol. User level security and Share level
  102. // security. Corresponding to each user in the user level security mode there is a session.
  103. //
  104. // Typically the password, user name and domain name strings associated with the session entry
  105. // revert to the default values, i.e., they are zero. In the event that they are not zero the
  106. // SessionString represents a concatenated version of the password,user name and domain name in
  107. // that order. This representation in a concatenated way yields us a savings of atleast 3
  108. // USHORT's over other representations.
  109. //
  110. typedef enum _SECURITY_MODE_ {
  111. SECURITY_MODE_SHARE_LEVEL = 0,
  112. SECURITY_MODE_USER_LEVEL = 1
  113. } SECURITY_MODE, *PSECURITY_MODE;
  114. #define SMBCE_SHARE_LEVEL_SERVER_USERID 0xffffffff
  115. typedef enum _SESSION_TYPE_ {
  116. UNINITIALIZED_SESSION,
  117. LANMAN_SESSION,
  118. EXTENDED_NT_SESSION
  119. } SESSION_TYPE, *PSESSION_TYPE;
  120. typedef enum _SMB_SESSION_KEY_STATE {
  121. SmbSessionKeyUnavailible = 0,
  122. SmbSessionKeyAuthenticating,
  123. SmbSessionKeyAvailible
  124. } SMB_SESSION_KEY_STATE;
  125. #define SMBCE_SESSION_FLAGS_LANMAN_SESSION_KEY_USED (0x002)
  126. #define SMBCE_SESSION_FLAGS_NULL_CREDENTIALS (0x004)
  127. #define SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION (0x008)
  128. #define SMBCE_SESSION_FLAGS_GUEST_SESSION (0x010)
  129. #define SMBCE_SESSION_FLAGS_LOGGED_OFF (0x020)
  130. #define SMBCE_SESSION_FLAGS_MARKED_FOR_DELETION (0x040)
  131. #define SMBCE_SESSION_FLAGS_SECSIG_ENABLED (0x080)
  132. #define SMBCE_SESSION_FLAGS_SESSION_KEY_HASHED (0x100)
  133. typedef struct _SMBCE_SESSION_ {
  134. SESSION_TYPE Type;
  135. SMB_USER_ID UserId;
  136. // Flags associated with the session.
  137. ULONG Flags;
  138. LUID LogonId;
  139. PUNICODE_STRING pUserName;
  140. PUNICODE_STRING pPassword;
  141. PUNICODE_STRING pUserDomainName;
  142. SMB_SESSION_KEY_STATE SessionKeyState;
  143. UCHAR UserSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  144. UCHAR UserNewSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  145. UCHAR LanmanSessionKey[MSV1_0_LANMAN_SESSION_KEY_LENGTH];
  146. // The credential and context handles.
  147. CtxtHandle SecurityContextHandle;
  148. CredHandle CredentialHandle;
  149. ULONG SessionId;
  150. ULONG SessionKeyLength;
  151. ULONG NumberOfActiveVNetRoot;
  152. ULONG TargetInfoLength;
  153. PUSHORT TargetInfoMarshalled;
  154. } SMBCE_SESSION, *PSMBCE_SESSION;
  155. extern VOID
  156. UninitializeSecurityContextsForSession(PSMBCE_SESSION pSession);
  157. extern VOID
  158. DeleteSecurityContextForSession(PSMBCE_SESSION pSession);
  159. //
  160. // SMBCE_*_SERVER -- This data structure encapsulates all the information related to a server.
  161. // Since there are multiple dialects of the SMB protocol, the capabilities as well as the
  162. // actions that need to be taken at the client machine are very different.
  163. //
  164. // Owing to the number of dialects of the SMB protocol we have two design possibilities.
  165. // Either we define an all encompassing data structure and have a code path that
  166. // uses the dialect and the capabilities of the connection to determine the action
  167. // required, or we use a subclassing mechanism associated with a dispatch vector.
  168. // The advantage of the second mechanism is that it can be developed incrementally and
  169. // it is very easily extensible. The disadvantage of this mechanism is that it can
  170. // lead to a very large footprint, if sufficient care is not exercised during
  171. // factorization and we could have lots and lots of procedure calls which has an
  172. // adverse effect on the code generated.
  173. //
  174. // We will adopt the second approach ( Thereby implicitly defining the metrics by
  175. // which the code should be evaluated !! ).
  176. //
  177. // The types of SMBCE_SERVER's can be classified in the following hierarchy
  178. //
  179. // SMBCE_SERVER
  180. //
  181. // SMBCE_USER_LEVEL_SERVER
  182. //
  183. // SMBCE_NT_SERVER
  184. //
  185. // SMBCE_SHARE_LEVEL_SERVER
  186. //
  187. // The dispatch vector which defines the set of methods supported by all the connections
  188. // (virtual functions in C++ terminology) are as follows
  189. //
  190. #define RAW_READ_CAPABILITY 0x0001
  191. #define RAW_WRITE_CAPABILITY 0x0002
  192. #define LWIO_CAPABILITY 0x0004
  193. #define COMPRESSED_DATA_CAPABILITY 0x0008
  194. #define ECHO_PROBE_IDLE 0x1
  195. #define ECHO_PROBE_AWAITING_RESPONSE 0x2
  196. #define CRYPT_TEXT_LEN MSV1_0_CHALLENGE_LENGTH
  197. typedef struct _NTLANMAN_SERVER_ {
  198. ULONG NtCapabilities;
  199. GUID ServerGuid;
  200. ULONG SecurityBlobLength;
  201. PVOID pSecurityBlob;
  202. } NTLANMAN_SERVER, *PNTLANMAN_SERVER;
  203. typedef struct _SMBCE_SERVER_ {
  204. // the server version count
  205. ULONG Version;
  206. // the dispatch vector
  207. struct _SMBCE_SERVER_DISPATCH_VECTOR_ *pDispatch;
  208. // the SMB dialect
  209. SMB_DIALECT Dialect;
  210. // More Server Capabilities
  211. ULONG DialectFlags;
  212. // the session key
  213. ULONG SessionKey;
  214. // the server Ip address
  215. ULONG IpAddress;
  216. // Security mode supported on the server
  217. SECURITY_MODE SecurityMode;
  218. // Time zone bias for conversion.
  219. LARGE_INTEGER TimeZoneBias;
  220. // Echo Expiry Time
  221. LARGE_INTEGER EchoExpiryTime;
  222. LONG SmbsReceivedSinceLastStrobe;
  223. //CSC stuff
  224. LONG CscState;
  225. LONG EchoProbeState;
  226. LONG NumberOfEchoProbesSent;
  227. // Maximum negotiated buffer size.
  228. ULONG MaximumBufferSize;
  229. // maximum buffer size for read/write operations
  230. ULONG MaximumDiskFileReadBufferSize;
  231. ULONG MaximumNonDiskFileReadBufferSize;
  232. ULONG MaximumDiskFileWriteBufferSize;
  233. ULONG MaximumNonDiskFileWriteBufferSize;
  234. // This is used to detect the number of server opens. If it is larger than 0,
  235. // we shouldn't tear down the current transport in case the user provides the transport.
  236. LONG NumberOfSrvOpens;
  237. LONG NumberOfVNetRootContextsForScavenging;
  238. LONG MidCounter;
  239. // Maximum number of multiplexed requests
  240. USHORT MaximumRequests;
  241. // Maximum number of VC's
  242. USHORT MaximumVCs;
  243. // Server Capabilities
  244. USHORT Capabilities;
  245. // encrypt passwords
  246. BOOLEAN EncryptPasswords;
  247. BOOLEAN SecuritySignaturesEnabled;
  248. BOOLEAN SecuritySignaturesRequired;
  249. // distinguishes a loopback connections
  250. BOOLEAN IsLoopBack;
  251. // TRUE if the same server is being referred to by multiple names
  252. BOOLEAN AliasedServers;
  253. BOOLEAN IsRemoteBootServer;
  254. // There are certain servers that return DF_NT_SMBS in the negotiate
  255. // but do not support change notifies. This allows us to suppress
  256. // change notify requests to those servers.
  257. BOOLEAN ChangeNotifyNotSupported;
  258. // avoid multiple event logs posted for security context failures
  259. BOOLEAN EventLogPosted;
  260. // The sessions on this server should use the extended timeout interval
  261. BOOLEAN ExtendedSessTimeout;
  262. USHORT EncryptionKeyLength;
  263. UCHAR EncryptionKey[CRYPT_TEXT_LEN];
  264. // Dialect specific information
  265. union {
  266. NTLANMAN_SERVER NtServer;
  267. };
  268. MD5_CTX SmbSecuritySignatureIntermediateContext;
  269. ULONG SmbSecuritySignatureIndex;
  270. BOOLEAN IsFakeDfsServerForOfflineUse;
  271. BOOLEAN IsPinnedOffline;
  272. } SMBCE_SERVER, *PSMBCE_SERVER;
  273. typedef
  274. NTSTATUS
  275. (*PBUILD_SESSION_SETUP_SMB)(
  276. IN OUT struct _SMB_EXCHANGE *pExchange,
  277. IN OUT PGENERIC_ANDX pSmb,
  278. IN OUT PULONG pBufferSize
  279. );
  280. typedef
  281. NTSTATUS
  282. (*PBUILD_TREE_CONNECT_SMB)(
  283. IN OUT struct _SMB_EXCHANGE *pExchange,
  284. IN OUT PGENERIC_ANDX pSmb,
  285. IN OUT PULONG pBufferSize
  286. );
  287. typedef struct _SMBCE_SERVER_DISPATCH_VECTOR_ {
  288. PBUILD_SESSION_SETUP_SMB BuildSessionSetup;
  289. PBUILD_TREE_CONNECT_SMB BuildTreeConnect;
  290. } SMBCE_SERVER_DISPATCH_VECTOR, *PSMBCE_SERVER_DISPATCH_VECTOR;
  291. #define SMBCE_SERVER_DIALECT_DISPATCH(pServer,Routine,Arguments) \
  292. (*((pServer)->pDispatch->Routine))##Arguments
  293. // The SMBCE engine process all requests in an asychronous fashion. Therefore for synchronous
  294. // requests an additional mechanism is required for synchronization. The following data structure
  295. // provides an easy way for implementing this synchronization.
  296. //
  297. // NOTE: For asynchronous resumption contexts the resumption routine can be invoked
  298. // at DPC level.
  299. #define SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS (0x1)
  300. typedef struct SMBCE_RESUMPTION_CONTEXT {
  301. ULONG Flags;
  302. NTSTATUS Status; // the status
  303. PVOID pContext; // a void pointer for clients to add additional context information
  304. union {
  305. PRX_WORKERTHREAD_ROUTINE pRoutine; // asynchronous contexts
  306. KEVENT Event; // the event for synchronization
  307. };
  308. BOOLEAN SecuritySignatureReturned;
  309. } SMBCE_RESUMPTION_CONTEXT, *PSMBCE_RESUMPTION_CONTEXT;
  310. #define SmbCeIsResumptionContextAsynchronous(pResumptionContext) \
  311. ((pResumptionContext)->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS)
  312. INLINE VOID
  313. SmbCeInitializeResumptionContext(
  314. PSMBCE_RESUMPTION_CONTEXT pResumptionContext)
  315. {
  316. KeInitializeEvent(&(pResumptionContext)->Event,NotificationEvent,FALSE);
  317. pResumptionContext->Status = STATUS_SUCCESS;
  318. pResumptionContext->Flags = 0;
  319. pResumptionContext->pContext = NULL;
  320. }
  321. INLINE VOID
  322. SmbCeInitializeAsynchronousResumptionContext(
  323. PSMBCE_RESUMPTION_CONTEXT pResumptionContext,
  324. PRX_WORKERTHREAD_ROUTINE pResumptionRoutine,
  325. PVOID pResumptionRoutineParam)
  326. {
  327. pResumptionContext->Status = STATUS_SUCCESS;
  328. pResumptionContext->Flags = SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS;
  329. pResumptionContext->pContext = pResumptionRoutineParam;
  330. pResumptionContext->pRoutine = pResumptionRoutine;
  331. }
  332. INLINE VOID
  333. SmbCeSuspend(
  334. PSMBCE_RESUMPTION_CONTEXT pResumptionContext)
  335. {
  336. ASSERT(!(pResumptionContext->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS));
  337. KeWaitForSingleObject(
  338. &pResumptionContext->Event,
  339. Executive,
  340. KernelMode,
  341. FALSE,
  342. NULL);
  343. }
  344. INLINE VOID
  345. SmbCeResume(
  346. PSMBCE_RESUMPTION_CONTEXT pResumptionContext)
  347. {
  348. if (!(pResumptionContext->Flags & SMBCE_RESUMPTION_CONTEXT_FLAG_ASYNCHRONOUS)) {
  349. KeSetEvent(&(pResumptionContext)->Event,0,FALSE);
  350. } else {
  351. if (RxShouldPostCompletion()) {
  352. RxDispatchToWorkerThread(
  353. MRxSmbDeviceObject,
  354. CriticalWorkQueue,
  355. pResumptionContext->pRoutine,
  356. pResumptionContext->pContext);
  357. } else {
  358. (pResumptionContext->pRoutine)(pResumptionContext->pContext);
  359. }
  360. }
  361. }
  362. //
  363. // The SMBCE_REQUEST struct encapsulates the continuation context associated. Typically
  364. // the act of sending a SMB along an exchange results in a SMBCE_REQUEST structure being
  365. // created with sufficient context information to resume the exchange upon reciept of
  366. // response from the serve. The SMBCE_REQUEST conatins ebough information to identify
  367. // the SMB for which the response is being obtained followed by enough context information
  368. // to resume the exchange.
  369. //
  370. typedef enum _SMBCE_OPERATION_ {
  371. SMBCE_TRANCEIVE,
  372. SMBCE_RECEIVE,
  373. SMBCE_SEND,
  374. SMBCE_ASYNCHRONOUS_SEND,
  375. SMBCE_ACQUIRE_MID
  376. } SMBCE_OPERATION, *PSMBCE_OPERATION;
  377. typedef enum _SMBCE_REQUEST_TYPE_ {
  378. ORDINARY_REQUEST,
  379. COPY_DATA_REQUEST,
  380. RECONNECT_REQUEST,
  381. ACQUIRE_MID_REQUEST,
  382. HOLD_REQUEST
  383. } SMBCE_REQUEST_TYPE, *PSMBCE_REQUEST_TYPE;
  384. typedef struct _SMBCE_GENERIC_REQUEST_ {
  385. SMBCE_REQUEST_TYPE Type;
  386. // the exchange instance that originated this SMB
  387. struct _SMB_EXCHANGE * pExchange;
  388. } SMBCE_GENERIC_REQUEST, *PSMBCE_GENERIC_REQUEST;
  389. //
  390. // The release routine prototype definition.
  391. //
  392. typedef
  393. NTSTATUS
  394. (*PSMBCE_RELEASE_ROUTINE) (
  395. struct _SMB_EXCHANGE * pExchange,
  396. PRX_CONTEXT pRxContext
  397. );
  398. //
  399. // Request to hold an exchange in suspension until someone releases it.
  400. //
  401. typedef struct _SMBCE_HOLD_REQUEST_ {
  402. SMBCE_GENERIC_REQUEST;
  403. PSMBCE_RELEASE_ROUTINE ReleaseRoutine;
  404. } SMBCE_HOLD_REQUEST, *PSMBCE_HOLD_REQUEST;
  405. typedef struct _SMBCE_REQUEST_ {
  406. SMBCE_GENERIC_REQUEST;
  407. // the type of request
  408. SMBCE_OPERATION Operation;
  409. // the virtual circuit along which this request was sent.
  410. PRXCE_VC pVc;
  411. // MPX Id of outgoing request.
  412. SMB_MPX_ID Mid;
  413. // the pedigree of the request
  414. SMB_TREE_ID TreeId; // The Tree Id.
  415. SMB_FILE_ID FileId; // The file id.
  416. SMB_USER_ID UserId; // User Id. for cancel.
  417. SMB_PROCESS_ID ProcessId; // Process Id. for cancel.
  418. PMDL pSendBuffer;
  419. ULONG BytesSent;
  420. } SMBCE_REQUEST, *PSMBCE_REQUEST;
  421. typedef struct _SMBCE_COPY_DATA_REQUEST_ {
  422. SMBCE_GENERIC_REQUEST;
  423. // the virtual circuit along which this request was sent.
  424. PRXCE_VC pVc;
  425. // the buffer into whihc data is being copied.
  426. PVOID pBuffer;
  427. // the actual number of bytes copied
  428. ULONG BytesCopied;
  429. } SMBCE_COPY_DATA_REQUEST, *PSMBCE_COPY_DATA_REQUEST;
  430. typedef struct _SMBCE_RECONNECT_REQUEST_ {
  431. SMBCE_GENERIC_REQUEST;
  432. } SMBCE_RECONNECT_REQUEST, *PSMBCE_RECONNECT_REQUEST;
  433. typedef struct _SMBCE_MID_REQUEST_ {
  434. SMBCE_GENERIC_REQUEST;
  435. PSMBCE_RESUMPTION_CONTEXT pResumptionContext;
  436. } SMBCE_MID_REQUEST, *PSMBCE_MID_REQUEST;
  437. //
  438. // extern function declarations
  439. //
  440. extern NTSTATUS
  441. BuildSessionSetupSmb(
  442. struct _SMB_EXCHANGE *pExchange,
  443. PGENERIC_ANDX pAndXSmb,
  444. PULONG pAndXSmbBufferSize);
  445. extern NTSTATUS
  446. CoreBuildTreeConnectSmb(
  447. struct _SMB_EXCHANGE *pExchange,
  448. PGENERIC_ANDX pAndXSmb,
  449. PULONG pAndXSmbBufferSize);
  450. extern NTSTATUS
  451. LmBuildTreeConnectSmb(
  452. struct _SMB_EXCHANGE *pExchange,
  453. PGENERIC_ANDX pAndXSmb,
  454. PULONG pAndXSmbBufferSize);
  455. extern NTSTATUS
  456. NtBuildTreeConnectSmb(
  457. struct _SMB_EXCHANGE *pExchange,
  458. PGENERIC_ANDX pAndXSmb,
  459. PULONG pAndXSmbBufferSize);
  460. extern NTSTATUS
  461. BuildNegotiateSmb(
  462. PVOID *pSmbBufferPointer,
  463. PULONG pSmbBufferLength,
  464. BOOLEAN RemoteBootSession);
  465. extern NTSTATUS
  466. ParseNegotiateResponse(
  467. IN OUT struct _SMB_ADMIN_EXCHANGE_ *pExchange,
  468. IN ULONG BytesIndicated,
  469. IN ULONG BytesAvailable,
  470. OUT PULONG pBytesTaken,
  471. IN PSMB_HEADER pSmbHeader,
  472. OUT PMDL *pDataBufferPointer,
  473. OUT PULONG pDataSize);
  474. extern NTSTATUS
  475. SmbCeHoldExchangeForSessionRecovery(
  476. struct _SMB_EXCHANGE *pExchange,
  477. PSMBCE_RELEASE_ROUTINE pRoutine
  478. );
  479. extern struct _MINIRDR_DISPATCH MRxSmbDispatch;
  480. #endif // _SMBCE_H_