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.

693 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. mssndrcv.c
  5. Abstract:
  6. This module implements all functions related to transmitting and recieving SMB's for
  7. mailslot related operations.
  8. Revision History:
  9. Balan Sethu Raman [SethuR] 6-June-1995
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "hostannc.h"
  15. #include "mssndrcv.h"
  16. // Forward references of functions ....
  17. //
  18. NTSTATUS
  19. MsUninitialize(PVOID pTransport);
  20. NTSTATUS
  21. MsInitializeExchange(
  22. PSMBCE_SERVER_TRANSPORT pTransport,
  23. PSMB_EXCHANGE pExchange);
  24. NTSTATUS
  25. MsTranceive(
  26. PSMBCE_SERVER_TRANSPORT pTransport,
  27. PSMBCEDB_SERVER_ENTRY pServerEntry,
  28. PSMB_EXCHANGE pExchange,
  29. ULONG SendOptions,
  30. PMDL pSmbMdl,
  31. ULONG SendLength,
  32. PVOID pSendCompletionContext);
  33. NTSTATUS
  34. MsReceive(
  35. PSMBCE_SERVER_TRANSPORT pTransport,
  36. PSMBCEDB_SERVER_ENTRY pServerEntry,
  37. PSMB_EXCHANGE pExchange);
  38. NTSTATUS
  39. MsSend(
  40. PSMBCE_SERVER_TRANSPORT pTransport,
  41. PSMBCEDB_SERVER_ENTRY pServerEntry,
  42. ULONG SendOptions,
  43. PMDL pSmbMdl,
  44. ULONG SendLength,
  45. PVOID pSendCompletionContext);
  46. NTSTATUS
  47. MsSendDatagram(
  48. PSMBCE_SERVER_TRANSPORT pTransport,
  49. PSMBCEDB_SERVER_ENTRY pServerEntry,
  50. ULONG SendOptions,
  51. PMDL pSmbMdl,
  52. ULONG SendLength,
  53. PVOID pSendCompletionContext);
  54. NTSTATUS
  55. MsInitializeExchange(
  56. PSMBCE_SERVER_TRANSPORT pTransport,
  57. PSMB_EXCHANGE pExchange);
  58. NTSTATUS
  59. MsUninitializeExchange(
  60. PSMBCE_SERVER_TRANSPORT pTransport,
  61. PSMB_EXCHANGE pExchange);
  62. VOID
  63. MsTimerEventHandler(
  64. PVOID pTransport);
  65. NTSTATUS
  66. MsInitiateDisconnect(
  67. PSMBCE_SERVER_TRANSPORT pServerTransport);
  68. #ifdef ALLOC_PRAGMA
  69. #pragma alloc_text(PAGE, MsInstantiateServerTransport)
  70. #pragma alloc_text(PAGE, MsTranceive)
  71. #pragma alloc_text(PAGE, MsReceive)
  72. #pragma alloc_text(PAGE, MsSend)
  73. #pragma alloc_text(PAGE, MsSendDatagram)
  74. #pragma alloc_text(PAGE, MsInitializeExchange)
  75. #pragma alloc_text(PAGE, MsUninitializeExchange)
  76. #pragma alloc_text(PAGE, MsTimerEventHandler)
  77. #pragma alloc_text(PAGE, MsInitiateDisconnect)
  78. #endif
  79. RXDT_DefineCategory(MSSNDRCV);
  80. #define Dbg (DEBUG_TRACE_MSSNDRCV)
  81. extern TRANSPORT_DISPATCH_VECTOR MRxSmbMailSlotTransportDispatch;
  82. #define SMBDATAGRAM_LOCAL_ENDPOINT_NAME "*SMBDATAGRAM "
  83. NTSTATUS
  84. MsInstantiateServerTransport(
  85. IN OUT PSMBCE_SERVER_TRANSPORT_CONSTRUCTION_CONTEXT pContext)
  86. /*++
  87. Routine Description:
  88. This routine initializes the MAILSLOT transport information corresponding to a server
  89. It allocates the transport address. It constructs two address strutures for the server
  90. name: a NETBIOS_EX type address and a NETBIOS type address. The latter only has up to the
  91. first 16 characters of the name, while a NETBIOS_EX may have more.
  92. Arguments:
  93. pContext - the transport construction context
  94. Return Value:
  95. STATUS_SUCCESS - the server transport construction has been finalized.
  96. Other Status codes correspond to error situations.
  97. Notes:
  98. The remote address can be either deduced from the information in the Rx Context
  99. or a NETBIOS address needs to be built from the server name.
  100. This transport address is used subsequently to establish the connection.
  101. // The last character of the name depends upon the path name passed in.
  102. // There are currently four possible alternatives ....
  103. //
  104. // \\*\mailslot\...... => the primary domain is used for broadcasts
  105. // (This mapping is handled by the RDBSS)
  106. //
  107. // \\Uniquename\mailslot\.... => maps to either a computer name or a group
  108. // name for mailslot writes.
  109. //
  110. // \\DomainName*\mailslot\.... => maps to a netbios address of the form
  111. // domainname ...1c for broadcasts.
  112. //
  113. // \\DomainName**\mailslot\.... => maps to a netbios address of the form
  114. // domainname....1b for broadcasts.
  115. //
  116. // Initialize the NETBIOS address according to these formats.
  117. Nbt.SendDatagram only looks at the first address. It is smart enough to treat a NETBIOS_EX
  118. address like a NETBIOS address when the length < NETBIOS_NAME_LEN. So if the name is
  119. short enough, I fill in byte 15 of the name for the NETBIOS_EX case as well.
  120. --*/
  121. {
  122. NTSTATUS Status;
  123. PSMBCEDB_SERVER_ENTRY pServerEntry;
  124. PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport;
  125. UNICODE_STRING ServerName;
  126. OEM_STRING OemServerName;
  127. ULONG ServerNameLength;
  128. PTRANSPORT_ADDRESS pTA;
  129. PTA_ADDRESS taa;
  130. PTDI_ADDRESS_NETBIOS na;
  131. PAGED_CODE();
  132. RxDbgTrace(0, Dbg, ("MsInitialize : Mailslot Transport Initialization\n"));
  133. ASSERT(pContext->State == SmbCeServerMailSlotTransportConstructionBegin);
  134. pServerEntry = pContext->pServerEntry;
  135. pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT)
  136. RxAllocatePoolWithTag(
  137. NonPagedPool,
  138. sizeof(SMBCE_SERVER_MAILSLOT_TRANSPORT),
  139. MRXSMB_MAILSLOT_POOLTAG);
  140. if (pMsTransport != NULL) {
  141. RtlZeroMemory(pMsTransport,sizeof(SMBCE_SERVER_MAILSLOT_TRANSPORT));
  142. ServerName.Buffer = pServerEntry->Name.Buffer + 1;
  143. ServerName.Length = pServerEntry->Name.Length - sizeof(WCHAR);
  144. ServerName.MaximumLength = pServerEntry->Name.MaximumLength - sizeof(WCHAR);
  145. ServerNameLength = RtlUnicodeStringToOemSize(&ServerName) - 1;
  146. pMsTransport->TransportAddressLength = FIELD_OFFSET(TRANSPORT_ADDRESS,Address)
  147. + (FIELD_OFFSET(TA_ADDRESS,Address))
  148. + TDI_ADDRESS_LENGTH_NETBIOS
  149. + 4 * sizeof(ULONG); // if the server name length is NETBIOS_NAME_LEN,
  150. // RtlUpcaseUnicodeStringToOemString could overrun the buffer.
  151. if (ServerNameLength > NETBIOS_NAME_LEN) {
  152. pMsTransport->TransportAddressLength += ServerNameLength;
  153. }
  154. pMsTransport->pTransportAddress = (PTRANSPORT_ADDRESS)RxAllocatePoolWithTag(
  155. NonPagedPool,
  156. pMsTransport->TransportAddressLength,
  157. MRXSMB_MAILSLOT_POOLTAG);
  158. if (pMsTransport->pTransportAddress != NULL) {
  159. pTA = pMsTransport->pTransportAddress;
  160. pTA->TAAddressCount = 1;
  161. // *****************************************
  162. // FIRST ADDRESS: TDI_ADDRESS_TYPE_NETBIOS
  163. // *****************************************
  164. taa = pTA->Address;
  165. taa->AddressLength = (USHORT) TDI_ADDRESS_LENGTH_NETBIOS;
  166. if (ServerNameLength > NETBIOS_NAME_LEN) {
  167. taa->AddressLength += (USHORT)(ServerNameLength - NETBIOS_NAME_LEN);
  168. }
  169. taa->AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  170. na = (PTDI_ADDRESS_NETBIOS) taa->Address;
  171. na->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE;
  172. OemServerName.MaximumLength = (USHORT) (ServerNameLength + 1); // in case null term
  173. OemServerName.Buffer = na->NetbiosName;
  174. Status = RtlUpcaseUnicodeStringToOemString(&OemServerName,
  175. &ServerName,
  176. FALSE);
  177. if (Status == STATUS_SUCCESS) {
  178. // Blank-pad the server name buffer if necessary to 16 characters
  179. if (OemServerName.Length <= NETBIOS_NAME_LEN) {
  180. RtlCopyMemory(&OemServerName.Buffer[OemServerName.Length],
  181. " ",
  182. NETBIOS_NAME_LEN - OemServerName.Length);
  183. }
  184. // Set type pneultimate byte in netbios name
  185. if (OemServerName.Buffer[OemServerName.Length - 1] == '*') {
  186. if (OemServerName.Length <= NETBIOS_NAME_LEN ||
  187. (OemServerName.Length == NETBIOS_NAME_LEN + 1 &&
  188. OemServerName.Buffer[OemServerName.Length - 2] == '*')) {
  189. if ((OemServerName.Length >= 2) &&
  190. (OemServerName.Buffer[OemServerName.Length - 2] == '*')) {
  191. if (OemServerName.Length <= NETBIOS_NAME_LEN) {
  192. OemServerName.Buffer[OemServerName.Length - 1] = ' ';
  193. OemServerName.Buffer[OemServerName.Length - 2] = ' ';
  194. } else {
  195. taa->AddressLength = (USHORT)TDI_ADDRESS_LENGTH_NETBIOS;
  196. }
  197. OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = PRIMARY_CONTROLLER_SIGNATURE;
  198. } else {
  199. OemServerName.Buffer[OemServerName.Length - 1] = ' ';
  200. OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = DOMAIN_CONTROLLER_SIGNATURE;
  201. }
  202. } else {
  203. Status = STATUS_BAD_NETWORK_PATH;
  204. }
  205. } else {
  206. OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = WORKSTATION_SIGNATURE;
  207. }
  208. }
  209. } else {
  210. Status = STATUS_INSUFFICIENT_RESOURCES;
  211. RxDbgTrace(0, Dbg, ("MsInitialize : Memory Allocation failed\n"));
  212. }
  213. if (Status == STATUS_SUCCESS) {
  214. pMsTransport->pTransport = NULL;
  215. pMsTransport->State = SMBCEDB_ACTIVE;
  216. pMsTransport->pDispatchVector = &MRxSmbMailSlotTransportDispatch;
  217. } else {
  218. RxDbgTrace(0, Dbg, ("MsInitialize : Mailsslot transport initialization Failed %lx\n",
  219. Status));
  220. MsUninitialize(pMsTransport);
  221. pMsTransport = NULL;
  222. }
  223. } else {
  224. RxDbgTrace(0, Dbg, ("MsInitialize : Memory Allocation failed\n"));
  225. Status = STATUS_INSUFFICIENT_RESOURCES;
  226. }
  227. if (Status == STATUS_SUCCESS) {
  228. pContext->pMailSlotTransport = (PSMBCE_SERVER_TRANSPORT)pMsTransport;
  229. } else {
  230. pContext->pMailSlotTransport = NULL;
  231. }
  232. pContext->State = SmbCeServerMailSlotTransportConstructionEnd;
  233. pContext->Status = Status;
  234. return Status;
  235. }
  236. NTSTATUS
  237. MsUninitialize(
  238. PSMBCE_SERVER_TRANSPORT pTransport)
  239. /*++
  240. Routine Description:
  241. This routine uninitializes the transport instance
  242. Arguments:
  243. pVcTransport - the VC transport instance
  244. Return Value:
  245. STATUS_SUCCESS - the server transport construction has been uninitialzied.
  246. Other Status codes correspond to error situations.
  247. Notes:
  248. --*/
  249. {
  250. NTSTATUS Status = STATUS_SUCCESS;
  251. PKEVENT pRundownEvent = pTransport->pRundownEvent;
  252. PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT)pTransport;
  253. PAGED_CODE();
  254. if (pMsTransport->pTransportAddress != NULL) {
  255. RxFreePool(pMsTransport->pTransportAddress);
  256. }
  257. RxFreePool(pMsTransport);
  258. if (pRundownEvent != NULL) {
  259. KeSetEvent(pRundownEvent, 0, FALSE );
  260. }
  261. return Status;
  262. }
  263. NTSTATUS
  264. MsInitiateDisconnect(
  265. PSMBCE_SERVER_TRANSPORT pTransport)
  266. /*++
  267. Routine Description:
  268. This routine uninitializes the transport instance
  269. Arguments:
  270. pTransport - the mailslot transport instance
  271. Return Value:
  272. STATUS_SUCCESS - the server transport construction has been uninitialzied.
  273. Other Status codes correspond to error situations.
  274. --*/
  275. {
  276. PAGED_CODE();
  277. return STATUS_SUCCESS;
  278. }
  279. NTSTATUS
  280. MsTranceive(
  281. PSMBCE_SERVER_TRANSPORT pTransport,
  282. PSMBCEDB_SERVER_ENTRY pServerEntry,
  283. PSMB_EXCHANGE pExchange,
  284. ULONG SendOptions,
  285. PMDL pSmbMdl,
  286. ULONG SendLength,
  287. PVOID pSendCompletionContext)
  288. /*++
  289. Routine Description:
  290. This routine transmits/receives a SMB for a give exchange
  291. Arguments:
  292. pTransport - the transport instance
  293. pServerEntry - the server entry
  294. pExchange - the exchange instance issuing this SMB.
  295. SendOptions - options for send
  296. pSmbMdl - the SMB that needs to be sent.
  297. SendLength - length of data to be transmitted
  298. Return Value:
  299. STATUS_SUCCESS - the server call construction has been finalized.
  300. STATUS_PENDING - the open involves network traffic and the exchange has been
  301. queued for notification ( pServerPointer is set to NULL)
  302. Other Status codes correspond to error situations.
  303. --*/
  304. {
  305. PAGED_CODE();
  306. return RX_MAP_STATUS(NOT_SUPPORTED);
  307. }
  308. NTSTATUS
  309. MsReceive(
  310. PSMBCE_SERVER_TRANSPORT pTransport,
  311. PSMBCEDB_SERVER_ENTRY pServerEntry,
  312. PSMB_EXCHANGE pExchange)
  313. /*++
  314. Routine Description:
  315. This routine transmits/receives a SMB for a give exchange
  316. Arguments:
  317. pTransport - the transport instance
  318. pServerEntry - the server entry
  319. pExchange - the exchange instance issuing this SMB.
  320. Return Value:
  321. STATUS_PENDING - the request has been queued
  322. Other Status codes correspond to error situations.
  323. --*/
  324. {
  325. PAGED_CODE();
  326. ASSERT(FALSE);
  327. return RX_MAP_STATUS(NOT_SUPPORTED);
  328. }
  329. NTSTATUS
  330. MsSend(
  331. PSMBCE_SERVER_TRANSPORT pTransport,
  332. PSMBCEDB_SERVER_ENTRY pServerEntry,
  333. ULONG SendOptions,
  334. PMDL pSmbMdl,
  335. ULONG SendLength,
  336. PVOID pSendCompletionContext)
  337. /*++
  338. Routine Description:
  339. This routine opens/creates a server entry in the connection engine database
  340. Arguments:
  341. pTransport - the transport instance
  342. pServer - the recepient server
  343. pVc - the Vc on which the SMB is sent( if it is NULL SMBCE picks one)
  344. SendOptions - options for send
  345. pSmbMdl - the SMB that needs to be sent.
  346. SendLength - length of data to be sent
  347. Return Value:
  348. STATUS_SUCCESS - the server call construction has been finalized.
  349. STATUS_PENDING - the open involves network traffic and the exchange has been
  350. queued for notification ( pServerPointer is set to NULL)
  351. Other Status codes correspond to error situations.
  352. --*/
  353. {
  354. NTSTATUS Status = STATUS_CONNECTION_DISCONNECTED;
  355. NTSTATUS FinalStatus = STATUS_CONNECTION_DISCONNECTED;
  356. PSMBCE_SERVER_MAILSLOT_TRANSPORT pMsTransport;
  357. PSMBCE_TRANSPORT pDatagramTransport;
  358. BOOLEAN fAtleastOneSendWasSuccessful = FALSE;
  359. PSMBCE_TRANSPORT_ARRAY pTransportArray;
  360. RXCE_CONNECTION_INFORMATION RxCeConnectionInformation;
  361. PAGED_CODE();
  362. pMsTransport = (PSMBCE_SERVER_MAILSLOT_TRANSPORT)pTransport;
  363. RxCeConnectionInformation.RemoteAddress = pMsTransport->pTransportAddress;
  364. RxCeConnectionInformation.RemoteAddressLength = pMsTransport->TransportAddressLength;
  365. RxCeConnectionInformation.UserDataLength = 0;
  366. RxCeConnectionInformation.UserData = NULL;
  367. RxCeConnectionInformation.OptionsLength = 0;
  368. RxCeConnectionInformation.Options = NULL;
  369. pTransportArray = SmbCeReferenceTransportArray();
  370. if (pTransportArray == NULL) {
  371. RxDbgTrace(0, Dbg, ("MsSend : Transport not available.\n"));
  372. return STATUS_NETWORK_UNREACHABLE;
  373. }
  374. if (pTransportArray != NULL) {
  375. ULONG i;
  376. for(i=0;i<pTransportArray->Count;i++) {
  377. pDatagramTransport = pTransportArray->SmbCeTransports[i];
  378. if (pDatagramTransport->Active &&
  379. (pDatagramTransport->RxCeTransport.pProviderInfo->MaxDatagramSize > 0)) {
  380. Status = RxCeSendDatagram(
  381. &pDatagramTransport->RxCeAddress,
  382. &RxCeConnectionInformation,
  383. SendOptions,
  384. pSmbMdl,
  385. SendLength,
  386. NULL);
  387. if (!NT_SUCCESS(Status)) {
  388. RxDbgTrace(0, Dbg, ("MsSend: RxCeSendDatagram on transport (%lx) returned %lx\n",pTransport,Status));
  389. FinalStatus = Status;
  390. } else {
  391. fAtleastOneSendWasSuccessful = TRUE;
  392. }
  393. }
  394. }
  395. }
  396. SmbCeDereferenceTransportArray(pTransportArray);
  397. if (fAtleastOneSendWasSuccessful) {
  398. SmbCeSendCompleteInd(pServerEntry,pSendCompletionContext,RX_MAP_STATUS(SUCCESS));
  399. Status = RX_MAP_STATUS(SUCCESS);
  400. } else {
  401. Status = FinalStatus;
  402. }
  403. return Status;
  404. }
  405. NTSTATUS
  406. MsSendDatagram(
  407. PSMBCE_SERVER_TRANSPORT pTransport,
  408. PSMBCEDB_SERVER_ENTRY pServerEntry,
  409. ULONG SendOptions,
  410. PMDL pSmbMdl,
  411. ULONG SendLength,
  412. PVOID pSendCompletionContext)
  413. /*++
  414. Routine Description:
  415. This routine opens/creates a server entry in the connection engine database
  416. Arguments:
  417. pTransport - the transport instance
  418. pServer - the recepient server
  419. SendOptions - options for send
  420. pSmbMdl - the SMB that needs to be sent.
  421. SendLength - length of data to be sent
  422. Return Value:
  423. STATUS_SUCCESS - the server call construction has been finalized.
  424. STATUS_PENDING - the open involves network traffic and the exchange has been
  425. queued for notification ( pServerPointer is set to NULL)
  426. Other Status codes correspond to error situations.
  427. --*/
  428. {
  429. PAGED_CODE();
  430. ASSERT(FALSE);
  431. return STATUS_NOT_IMPLEMENTED;
  432. }
  433. NTSTATUS
  434. MsInitializeExchange(
  435. PSMBCE_SERVER_TRANSPORT pTransport,
  436. PSMB_EXCHANGE pExchange)
  437. /*++
  438. Routine Description:
  439. This routine initializes the transport information pertinent to a exchange
  440. Arguments:
  441. pTransport - the transport structure
  442. pExchange - the exchange instance
  443. Return Value:
  444. STATUS_SUCCESS -
  445. Other Status codes correspond to error situations.
  446. --*/
  447. {
  448. return STATUS_SUCCESS;
  449. }
  450. NTSTATUS
  451. MsUninitializeExchange(
  452. PSMBCE_SERVER_TRANSPORT pTransport,
  453. PSMB_EXCHANGE pExchange)
  454. /*++
  455. Routine Description:
  456. This routine uninitializes the transport information pertinent to a exchange
  457. Arguments:
  458. pTransport - the transport structure
  459. pExchange - the exchange instance
  460. Return Value:
  461. STATUS_SUCCESS -
  462. Other Status codes correspond to error situations.
  463. --*/
  464. {
  465. PAGED_CODE();
  466. return STATUS_SUCCESS;
  467. }
  468. VOID
  469. MsTimerEventHandler(
  470. PVOID pTransport)
  471. /*++
  472. Routine Description:
  473. This routine handles the periodic strobes to determine if the connection is still alive
  474. Arguments:
  475. pTransport - the recepient server
  476. Notes:
  477. This routine is not implemented for mail slot related transports
  478. --*/
  479. {
  480. PAGED_CODE();
  481. }
  482. TRANSPORT_DISPATCH_VECTOR
  483. MRxSmbMailSlotTransportDispatch = {
  484. MsSend,
  485. MsSendDatagram,
  486. MsTranceive,
  487. MsReceive,
  488. MsTimerEventHandler,
  489. MsInitializeExchange,
  490. MsUninitializeExchange,
  491. MsUninitialize,
  492. MsInitiateDisconnect
  493. };
  494. 
  495.