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.

1952 lines
57 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. tdi.c
  5. Abstract:
  6. This module contains code which assists the process of writing an NT
  7. TDI client.
  8. Author:
  9. David Beaver (dbeaver) 15 June 1991
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include <ntosp.h>
  15. #include <zwapi.h>
  16. #include <ndis.h>
  17. #include <tdikrnl.h>
  18. #include "tdipnp.h"
  19. #if DBG
  20. #include "tdidebug.h"
  21. ULONG TdiDebug;
  22. #define IF_TDIDBG(sts) \
  23. if ((TdiDebug & sts) != 0)
  24. #define TDI_DEBUG_NAMES 0x00000001
  25. #define TDI_DEBUG_DISPATCH 0x00000002
  26. #define TDI_DEBUG_MAP 0x00000004
  27. #else
  28. #define IF_TDIDBG(sts) \
  29. if (0)
  30. #endif
  31. ULONG TdiInitializationCount;
  32. NTSTATUS
  33. DriverEntry(
  34. IN PDRIVER_OBJECT DriverObject,
  35. IN PUNICODE_STRING RegistryPath
  36. )
  37. /*++
  38. Routine Description:
  39. Temporary entry point needed to initialize the TDI wrapper driver.
  40. Arguments:
  41. DriverObject - Pointer to the driver object created by the system.
  42. Return Value:
  43. STATUS_SUCCESS
  44. --*/
  45. {
  46. //
  47. // Note: This function isn't called but is needed to keep the
  48. // linker happy.
  49. //
  50. UNREFERENCED_PARAMETER(DriverObject);
  51. return STATUS_SUCCESS;
  52. } // DriverEntry
  53. NTSTATUS
  54. TdiMapUserRequest(
  55. IN PDEVICE_OBJECT DeviceObject,
  56. IN PIRP Irp,
  57. IN PIO_STACK_LOCATION IrpSp
  58. )
  59. /*++
  60. Routine Description:
  61. This routine maps a user request from the NtDeviceIoControlFile format
  62. to the kernel mode request format. It does this by probing and locking all
  63. buffers of interest, copying parameter sets to the stack pointer as
  64. appropriate, and generally preparing for the kernel IO form.
  65. Arguments:
  66. Irp - pointer to the irp containing this request.
  67. Return Value:
  68. NTSTATUS - status of operation. STATUS_UNSUCCESSFUL if the request could
  69. not be mapped, STATUS_NOT_IMPLEMENTED if the IOCTL is not recognized
  70. (allowing driver writers to extend the supported IOCTLs if needed), and
  71. STATUS_SUCCESS if the request was mapped successfully.
  72. --*/
  73. {
  74. NTSTATUS Status;
  75. DeviceObject;
  76. Status = STATUS_INVALID_PARAMETER;
  77. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  78. case IOCTL_TDI_ACCEPT:
  79. if (Irp->RequestorMode == UserMode) {
  80. return STATUS_NOT_IMPLEMENTED;
  81. }
  82. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  83. IrpSp->MinorFunction = TDI_ACCEPT;
  84. Status = STATUS_SUCCESS;
  85. break;
  86. case IOCTL_TDI_ACTION:
  87. #if defined(_WIN64)
  88. if (IoIs32bitProcess(Irp)) {
  89. return STATUS_NOT_IMPLEMENTED;
  90. }
  91. #endif // _WIN64
  92. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  93. IrpSp->MinorFunction = TDI_ACTION;
  94. Status = STATUS_SUCCESS;
  95. break;
  96. case IOCTL_TDI_CONNECT:
  97. {
  98. PTDI_REQUEST_CONNECT userRequest;
  99. PTDI_REQUEST_KERNEL_CONNECT request;
  100. PTDI_CONNECTION_INFORMATION connInfo;
  101. PCHAR ptr;
  102. KPROCESSOR_MODE PreviousMode;
  103. if (Irp->RequestorMode == UserMode) {
  104. return STATUS_NOT_IMPLEMENTED;
  105. }
  106. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_CONNECT) ) {
  107. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  108. IrpSp->MinorFunction = TDI_CONNECT;
  109. userRequest =
  110. (PTDI_REQUEST_CONNECT)Irp->AssociatedIrp.SystemBuffer;
  111. connInfo = userRequest->RequestConnectionInformation;
  112. ptr = (PCHAR)(connInfo + 1);
  113. connInfo->UserData = ptr;
  114. ptr += connInfo->UserDataLength;
  115. connInfo->Options = ptr;
  116. ptr += connInfo->OptionsLength;
  117. connInfo->RemoteAddress = ptr;
  118. request = (PTDI_REQUEST_KERNEL_CONNECT)&IrpSp->Parameters;
  119. request->RequestConnectionInformation = connInfo;
  120. request->ReturnConnectionInformation = NULL;
  121. Status = STATUS_SUCCESS;
  122. }
  123. break;
  124. }
  125. case IOCTL_TDI_DISCONNECT:
  126. {
  127. if (Irp->RequestorMode == UserMode) {
  128. return STATUS_NOT_IMPLEMENTED;
  129. }
  130. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  131. IrpSp->MinorFunction = TDI_DISCONNECT;
  132. Status = STATUS_SUCCESS;
  133. break;
  134. }
  135. case IOCTL_TDI_LISTEN:
  136. {
  137. PTDI_REQUEST_LISTEN userRequest;
  138. PTDI_REQUEST_KERNEL_LISTEN request;
  139. if (Irp->RequestorMode == UserMode) {
  140. return STATUS_NOT_IMPLEMENTED;
  141. }
  142. //
  143. // fix for 123633
  144. //
  145. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_LISTEN)) {
  146. userRequest =
  147. (PTDI_REQUEST_LISTEN)Irp->AssociatedIrp.SystemBuffer;
  148. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  149. IrpSp->MinorFunction = TDI_LISTEN;
  150. request = (PTDI_REQUEST_KERNEL_LISTEN)&IrpSp->Parameters;
  151. request->RequestFlags = userRequest->ListenFlags;
  152. Status = STATUS_SUCCESS;
  153. }
  154. break;
  155. }
  156. case IOCTL_TDI_QUERY_INFORMATION:
  157. {
  158. PTDI_REQUEST_QUERY_INFORMATION userRequest;
  159. PTDI_REQUEST_KERNEL_QUERY_INFORMATION request;
  160. PTDI_CONNECTION_INFORMATION connInfo;
  161. UINT RemainingSize;
  162. PCHAR ptr;
  163. #if defined(_WIN64)
  164. if (IoIs32bitProcess(Irp)) {
  165. return STATUS_NOT_IMPLEMENTED;
  166. }
  167. #endif // _WIN64
  168. RemainingSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  169. //
  170. // 123634
  171. //
  172. if (RemainingSize >= sizeof(TDI_REQUEST_QUERY_INFORMATION)) {
  173. userRequest =
  174. (PTDI_REQUEST_QUERY_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  175. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  176. IrpSp->MinorFunction = TDI_QUERY_INFORMATION;
  177. request = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
  178. request->QueryType = userRequest->QueryType;
  179. RemainingSize -= sizeof(TDI_REQUEST_QUERY_INFORMATION);
  180. if (RemainingSize >= sizeof(TDI_CONNECTION_INFORMATION))
  181. {
  182. connInfo = (PTDI_CONNECTION_INFORMATION)(userRequest + 1);
  183. ptr = (PCHAR)(connInfo + 1);
  184. connInfo->UserData = ptr;
  185. ptr += connInfo->UserDataLength;
  186. connInfo->Options = ptr;
  187. ptr += connInfo->OptionsLength;
  188. connInfo->RemoteAddress = ptr;
  189. request->RequestConnectionInformation = connInfo;
  190. }
  191. else
  192. {
  193. request->RequestConnectionInformation = NULL;
  194. }
  195. Status = STATUS_SUCCESS;
  196. }
  197. break;
  198. }
  199. case IOCTL_TDI_RECEIVE:
  200. {
  201. PTDI_REQUEST_RECEIVE userRequest;
  202. PTDI_REQUEST_KERNEL_RECEIVE request;
  203. ULONG receiveLength;
  204. if (Irp->RequestorMode == UserMode) {
  205. return STATUS_NOT_IMPLEMENTED;
  206. }
  207. //
  208. // 123635
  209. //
  210. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_RECEIVE)) {
  211. userRequest =
  212. (PTDI_REQUEST_RECEIVE)Irp->AssociatedIrp.SystemBuffer;
  213. receiveLength =
  214. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  215. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  216. IrpSp->MinorFunction = TDI_RECEIVE;
  217. request = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
  218. request->ReceiveLength = receiveLength;
  219. request->ReceiveFlags = userRequest->ReceiveFlags;
  220. Status = STATUS_SUCCESS;
  221. }
  222. break;
  223. }
  224. case IOCTL_TDI_RECEIVE_DATAGRAM:
  225. {
  226. PTDI_REQUEST_RECEIVE_DATAGRAM userRequest;
  227. PTDI_REQUEST_KERNEL_RECEIVEDG request;
  228. ULONG receiveLength;
  229. if (Irp->RequestorMode == UserMode) {
  230. return STATUS_NOT_IMPLEMENTED;
  231. }
  232. //
  233. // 123636
  234. //
  235. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_RECEIVE_DATAGRAM)) {
  236. userRequest =
  237. (PTDI_REQUEST_RECEIVE_DATAGRAM)Irp->AssociatedIrp.SystemBuffer;
  238. receiveLength =
  239. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  240. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  241. IrpSp->MinorFunction = TDI_RECEIVE_DATAGRAM;
  242. request = (PTDI_REQUEST_KERNEL_RECEIVEDG)&IrpSp->Parameters;
  243. request->ReceiveLength = receiveLength;
  244. request->ReceiveFlags = userRequest->ReceiveFlags;
  245. request->ReceiveDatagramInformation = userRequest->ReceiveDatagramInformation;
  246. request->ReturnDatagramInformation = userRequest->ReturnInformation;
  247. Status = STATUS_SUCCESS;
  248. }
  249. break;
  250. }
  251. case IOCTL_TDI_SEND:
  252. {
  253. PTDI_REQUEST_SEND userRequest;
  254. PTDI_REQUEST_KERNEL_SEND request;
  255. ULONG sendLength;
  256. if (Irp->RequestorMode == UserMode) {
  257. return STATUS_NOT_IMPLEMENTED;
  258. }
  259. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_SEND)) {
  260. userRequest =
  261. (PTDI_REQUEST_SEND)Irp->AssociatedIrp.SystemBuffer;
  262. sendLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  263. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  264. IrpSp->MinorFunction = TDI_SEND;
  265. request = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters;
  266. request->SendLength = sendLength;
  267. request->SendFlags = userRequest->SendFlags;
  268. Status = STATUS_SUCCESS;
  269. }
  270. break;
  271. }
  272. case IOCTL_TDI_SEND_DATAGRAM:
  273. {
  274. PTDI_REQUEST_SEND_DATAGRAM userRequest;
  275. PTDI_REQUEST_KERNEL_SENDDG request;
  276. ULONG sendLength;
  277. if (Irp->RequestorMode == UserMode) {
  278. return STATUS_NOT_IMPLEMENTED;
  279. }
  280. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_SEND_DATAGRAM)) {
  281. sendLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  282. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  283. IrpSp->MinorFunction = TDI_SEND_DATAGRAM;
  284. request = (PTDI_REQUEST_KERNEL_SENDDG)&IrpSp->Parameters;
  285. request->SendLength = sendLength;
  286. userRequest = (PTDI_REQUEST_SEND_DATAGRAM)Irp->AssociatedIrp.SystemBuffer;
  287. request->SendDatagramInformation = userRequest->SendDatagramInformation;
  288. Status = STATUS_SUCCESS;
  289. }
  290. break;
  291. }
  292. case IOCTL_TDI_SET_EVENT_HANDLER:
  293. //
  294. // Because this request will enable direct callouts from the
  295. // transport provider at DISPATCH_LEVEL to a client-specified
  296. // routine, this request is only valid in kernel mode, denying
  297. // access to this request in user mode.
  298. //
  299. Status = STATUS_INVALID_PARAMETER;
  300. break;
  301. case IOCTL_TDI_SET_INFORMATION:
  302. {
  303. PTDI_REQUEST_SET_INFORMATION userRequest;
  304. PTDI_REQUEST_KERNEL_SET_INFORMATION request;
  305. #if defined(_WIN64)
  306. if (IoIs32bitProcess(Irp)) {
  307. return STATUS_NOT_IMPLEMENTED;
  308. }
  309. #endif // _WIN64
  310. //
  311. // 123637
  312. //
  313. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_SET_INFORMATION)) {
  314. userRequest =
  315. (PTDI_REQUEST_SET_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  316. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  317. IrpSp->MinorFunction = TDI_SET_INFORMATION;
  318. request = (PTDI_REQUEST_KERNEL_SET_INFORMATION)&IrpSp->Parameters;
  319. request->SetType = userRequest->SetType;
  320. request->RequestConnectionInformation = NULL;
  321. Status = STATUS_SUCCESS;
  322. }
  323. break;
  324. }
  325. case IOCTL_TDI_ASSOCIATE_ADDRESS:
  326. {
  327. PTDI_REQUEST_ASSOCIATE_ADDRESS userRequest;
  328. PTDI_REQUEST_KERNEL_ASSOCIATE request;
  329. if (Irp->RequestorMode == UserMode) {
  330. return STATUS_NOT_IMPLEMENTED;
  331. }
  332. //
  333. // 123637
  334. //
  335. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength == sizeof(TDI_REQUEST_ASSOCIATE_ADDRESS)) {
  336. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  337. IrpSp->MinorFunction = TDI_ASSOCIATE_ADDRESS;
  338. userRequest =
  339. (PTDI_REQUEST_ASSOCIATE_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
  340. request = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
  341. request->AddressHandle = userRequest->AddressHandle;
  342. Status = STATUS_SUCCESS;
  343. }
  344. break;
  345. }
  346. case IOCTL_TDI_DISASSOCIATE_ADDRESS:
  347. {
  348. if (Irp->RequestorMode == UserMode) {
  349. return STATUS_NOT_IMPLEMENTED;
  350. }
  351. IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  352. IrpSp->MinorFunction = TDI_DISASSOCIATE_ADDRESS;
  353. Status = STATUS_SUCCESS;
  354. break;
  355. }
  356. default:
  357. Status = STATUS_NOT_IMPLEMENTED;
  358. break;
  359. }
  360. return Status;
  361. }
  362. NTSTATUS
  363. TdiDefaultConnectHandler(
  364. IN PVOID TdiEventContext,
  365. IN LONG RemoteAddressLength,
  366. IN PVOID RemoteAddress,
  367. IN LONG UserDataLength,
  368. IN PVOID UserData,
  369. IN LONG OptionsLength,
  370. IN PVOID Options,
  371. OUT CONNECTION_CONTEXT *ConnectionContext,
  372. OUT PIRP *AcceptIrp
  373. )
  374. /*++
  375. Routine Description:
  376. This routine is called when a connect request has completed. The connection
  377. is fully functional when the indication occurs.
  378. Arguments:
  379. TdiEventContext - the context value passed in by the user in the Set Event Handler call
  380. RemoteAddressLength,
  381. RemoteAddress,
  382. UserDataLength,
  383. UserData,
  384. OptionsLength,
  385. Options,
  386. ConnectionId
  387. Return Value:
  388. The function value is the final status from the initialization operation.
  389. --*/
  390. {
  391. UNREFERENCED_PARAMETER (TdiEventContext);
  392. UNREFERENCED_PARAMETER (RemoteAddressLength);
  393. UNREFERENCED_PARAMETER (RemoteAddress);
  394. UNREFERENCED_PARAMETER (UserDataLength);
  395. UNREFERENCED_PARAMETER (UserData);
  396. UNREFERENCED_PARAMETER (OptionsLength);
  397. UNREFERENCED_PARAMETER (Options);
  398. UNREFERENCED_PARAMETER (ConnectionContext);
  399. return STATUS_INSUFFICIENT_RESOURCES; // do nothing
  400. }
  401. NTSTATUS
  402. TdiDefaultDisconnectHandler(
  403. IN PVOID TdiEventContext,
  404. IN CONNECTION_CONTEXT ConnectionContext,
  405. IN LONG DisconnectDataLength,
  406. IN PVOID DisconnectData,
  407. IN LONG DisconnectInformationLength,
  408. IN PVOID DisconnectInformation,
  409. IN ULONG DisconnectFlags
  410. )
  411. /*++
  412. Routine Description:
  413. This routine is used as the default disconnect event handler
  414. for the transport endpoint. It is pointed to by a field in the
  415. TP_ENDPOINT structure for an endpoint when the endpoint is
  416. created, and also whenever the TdiSetEventHandler request is
  417. submitted with a NULL EventHandler field.
  418. Arguments:
  419. TransportEndpoint - Pointer to open file object.
  420. Context - Typeless pointer specifying connection context.
  421. DisconnectIndicators - Value indicating reason for disconnection indication.
  422. Return Value:
  423. NTSTATUS - status of operation.
  424. --*/
  425. {
  426. UNREFERENCED_PARAMETER (TdiEventContext);
  427. UNREFERENCED_PARAMETER (ConnectionContext);
  428. UNREFERENCED_PARAMETER (DisconnectDataLength);
  429. UNREFERENCED_PARAMETER (DisconnectData);
  430. UNREFERENCED_PARAMETER (DisconnectInformationLength);
  431. UNREFERENCED_PARAMETER (DisconnectInformation);
  432. UNREFERENCED_PARAMETER (DisconnectFlags);
  433. return STATUS_SUCCESS; // do nothing but return successfully.
  434. } /* DefaultDisconnectHandler */
  435. NTSTATUS
  436. TdiDefaultErrorHandler(
  437. IN PVOID TdiEventContext, // the endpoint's file object.
  438. IN NTSTATUS Status // status code indicating error type.
  439. )
  440. /*++
  441. Routine Description:
  442. This routine is used as the default error event handler for
  443. the transport endpoint. It is pointed to by a field in the
  444. TP_ENDPOINT structure for an endpoint when the endpoint is
  445. created, and also whenever the TdiSetEventHandler request is
  446. submitted with a NULL EventHandler field.
  447. Arguments:
  448. TransportEndpoint - Pointer to open file object.
  449. Status - Status code indicated by this event.
  450. Return Value:
  451. NTSTATUS - status of operation.
  452. --*/
  453. {
  454. UNREFERENCED_PARAMETER (TdiEventContext);
  455. UNREFERENCED_PARAMETER (Status);
  456. return STATUS_SUCCESS; // do nothing but return successfully.
  457. } /* DefaultErrorHandler */
  458. NTSTATUS
  459. TdiDefaultReceiveHandler(
  460. IN PVOID TdiEventContext,
  461. IN CONNECTION_CONTEXT ConnectionContext,
  462. IN ULONG ReceiveFlags,
  463. IN ULONG BytesIndicated,
  464. IN ULONG BytesAvailable,
  465. OUT ULONG *BytesTaken,
  466. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  467. OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  468. )
  469. /*++
  470. Routine Description:
  471. This routine is used as the default receive event handler for
  472. the transport endpoint. It is pointed to by a field in the
  473. TP_ENDPOINT structure for an endpoint when the endpoint is
  474. created, and also whenever the TdiSetEventHandler request is
  475. submitted with a NULL EventHandler field.
  476. Arguments:
  477. TdiEventContext - Pointer to the client-provided context value specified
  478. in the TdiSetEventHandler call for TDI_EVENT_RECEIVE.
  479. ConnectionContext - The client-supplied context associated with
  480. the connection on which this connection-oriented TSDU was received.
  481. ReceiveFlags - Bitflags which indicate the circumstances surrounding
  482. this TSDU's reception.
  483. BytesIndicated - The number of bytes of this TSDU that are being presented
  484. to the client in this indication.This value is always less than
  485. or equal to BytesAvailable.
  486. BytesAvailable - The total number of bytes of this TSDU presently
  487. available from the transport.
  488. BytesTaken - Return value indicating the number of bytes of data that the
  489. client copied from the indication data.
  490. Tsdu - Pointer to an MDL chain that describes the (first) part of the
  491. (partially) received Transport Service Data Unit, less headers.
  492. IoRequestPacket - Pointer to a location where the event handler may
  493. chose to return a pointer to an I/O Request Packet (IRP) to satisfy
  494. the incoming data. If returned, this IRP must be formatted as a
  495. valid TdiReceive request, except that the ConnectionId field of
  496. the TdiRequest is ignored and is automatically filled in by the
  497. transport provider.
  498. Return Value:
  499. NTSTATUS - status of operation.
  500. --*/
  501. {
  502. UNREFERENCED_PARAMETER (TdiEventContext);
  503. UNREFERENCED_PARAMETER (ConnectionContext);
  504. UNREFERENCED_PARAMETER (ReceiveFlags);
  505. UNREFERENCED_PARAMETER (BytesIndicated);
  506. UNREFERENCED_PARAMETER (BytesAvailable);
  507. UNREFERENCED_PARAMETER (BytesTaken);
  508. UNREFERENCED_PARAMETER (Tsdu);
  509. UNREFERENCED_PARAMETER (IoRequestPacket);
  510. return STATUS_DATA_NOT_ACCEPTED; // no handler in place.
  511. } /* DefaultReceiveHandler */
  512. NTSTATUS
  513. TdiDefaultRcvDatagramHandler(
  514. IN PVOID TdiEventContext, // the event context
  515. IN LONG SourceAddressLength, // length of the originator of the datagram
  516. IN PVOID SourceAddress, // string describing the originator of the datagram
  517. IN LONG OptionsLength, // options for the receive
  518. IN PVOID Options, //
  519. IN ULONG ReceiveDatagramFlags, //
  520. IN ULONG BytesIndicated, // number of bytes this indication
  521. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  522. OUT ULONG *BytesTaken, // number of bytes used
  523. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  524. OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  525. )
  526. /*++
  527. Routine Description:
  528. This routine is used as the default receive datagram event
  529. handler for the transport endpoint. It is pointed to by a
  530. field in the TP_ENDPOINT structure for an endpoint when the
  531. endpoint is created, and also whenever the TdiSetEventHandler
  532. request is submitted with a NULL EventHandler field.
  533. Arguments:
  534. TdiEventContext - Pointer to the client-provided context value specified
  535. in the TdiSetEventHandler call for TDI_EVENT_RECEIVE_DATAGRAM.
  536. DestinationAddress - Pointer to the network name of the destination
  537. to which the datagram was directed.
  538. SourceAddress - Pointer to the network name of the source from which
  539. the datagram originated.
  540. Tsap - Transport service access point on which this datagram was received.
  541. ReceiveIndicators - Bitflags which indicate the circumstances surrounding
  542. this TSDU's reception.
  543. Tsdu - Pointer to an MDL chain that describes the (first) part of the
  544. (partially) received Transport Service Data Unit, less headers.
  545. IoRequestPacket - Pointer to a location where the event handler may
  546. chose to return a pointer to an I/O Request Packet (IRP) to satisfy
  547. the incoming data. If returned, this IRP must be formatted as a
  548. valid TdiReceiveDatagram request.
  549. Return Value:
  550. NTSTATUS - status of operation.
  551. --*/
  552. {
  553. UNREFERENCED_PARAMETER (TdiEventContext);
  554. UNREFERENCED_PARAMETER (SourceAddressLength);
  555. UNREFERENCED_PARAMETER (SourceAddress);
  556. UNREFERENCED_PARAMETER (OptionsLength);
  557. UNREFERENCED_PARAMETER (Options);
  558. UNREFERENCED_PARAMETER (BytesIndicated);
  559. UNREFERENCED_PARAMETER (BytesAvailable);
  560. UNREFERENCED_PARAMETER (BytesTaken);
  561. UNREFERENCED_PARAMETER (Tsdu);
  562. UNREFERENCED_PARAMETER (IoRequestPacket);
  563. return STATUS_DATA_NOT_ACCEPTED; // no handler in place.
  564. } /* DefaultRcvDatagramHandler */
  565. NTSTATUS
  566. TdiDefaultRcvExpeditedHandler(
  567. IN PVOID TdiEventContext,
  568. IN CONNECTION_CONTEXT ConnectionContext,
  569. IN ULONG ReceiveFlags, //
  570. IN ULONG BytesIndicated, // number of bytes in this indication
  571. IN ULONG BytesAvailable, // number of bytes in complete Tsdu
  572. OUT ULONG *BytesTaken, // number of bytes used by indication routine
  573. IN PVOID Tsdu, // pointer describing this TSDU, typically a lump of bytes
  574. OUT PIRP *IoRequestPacket // TdiReceive IRP if MORE_PROCESSING_REQUIRED.
  575. )
  576. /*++
  577. Routine Description:
  578. This routine is used as the default expedited receive event handler
  579. for the transport endpoint. It is pointed to by a field in the
  580. TP_ENDPOINT structure for an endpoint when the endpoint is
  581. created, and also whenever the TdiSetEventHandler request is
  582. submitted with a NULL EventHandler field.
  583. Arguments:
  584. TdiEventContext - Pointer to the client-provided context value specified
  585. in the TdiSetEventHandler call for TDI_EVENT_RECEIVE.
  586. ConnectionContext - The client-supplied context associated with
  587. the connection on which this connection-oriented TSDU was received.
  588. ReceiveFlags - Bitflags which indicate the circumstances surrounding
  589. this TSDU's reception.
  590. BytesIndicated - The number of bytes of this TSDU that are being presented
  591. to the client in this indication.This value is always less than
  592. or equal to BytesAvailable.
  593. BytesAvailable - The total number of bytes of this TSDU presently
  594. available from the transport.
  595. BytesTaken - Return value indicating the number of bytes of data that the
  596. client copied from the indication data.
  597. Tsdu - Pointer to an MDL chain that describes the (first) part of the
  598. (partially) received Transport Service Data Unit, less headers.
  599. IoRequestPacket - Pointer to a location where the event handler may
  600. chose to return a pointer to an I/O Request Packet (IRP) to satisfy
  601. the incoming data. If returned, this IRP must be formatted as a
  602. valid TdiReceive request, except that the ConnectionId field of
  603. the TdiRequest is ignored and is automatically filled in by the
  604. transport provider.
  605. Return Value:
  606. NTSTATUS - status of operation.
  607. --*/
  608. {
  609. UNREFERENCED_PARAMETER (TdiEventContext);
  610. UNREFERENCED_PARAMETER (ConnectionContext);
  611. UNREFERENCED_PARAMETER (ReceiveFlags);
  612. UNREFERENCED_PARAMETER (BytesIndicated);
  613. UNREFERENCED_PARAMETER (BytesAvailable);
  614. UNREFERENCED_PARAMETER (BytesTaken);
  615. UNREFERENCED_PARAMETER (Tsdu);
  616. UNREFERENCED_PARAMETER (IoRequestPacket);
  617. return STATUS_DATA_NOT_ACCEPTED;
  618. } /* DefaultRcvExpeditedHandler */
  619. NTSTATUS
  620. TdiDefaultChainedReceiveHandler (
  621. IN PVOID TdiEventContext,
  622. IN CONNECTION_CONTEXT ConnectionContext,
  623. IN ULONG ReceiveFlags,
  624. IN ULONG ReceiveLength,
  625. IN ULONG StartingOffset,
  626. IN PMDL Tsdu,
  627. IN PVOID TsduDescriptor
  628. )
  629. /*++
  630. Routine Description:
  631. This routine is used as the default chanied receive event handler
  632. for the transport endpoint. It is pointed to by a field in the
  633. TP_ENDPOINT structure for an endpoint when the endpoint is
  634. created, and also whenever the TdiSetEventHandler request is
  635. submitted with a NULL EventHandler field.
  636. Arguments:
  637. TdiEventContext - Pointer to the client-provided context value specified
  638. in the TdiSetEventHandler call for TDI_EVENT_CHAINED_RECEIVE.
  639. ConnectionContext - The client-supplied context associated with
  640. the connection on which this connection-oriented TSDU was received.
  641. ReceiveFlags - Bitflags which indicate the circumstances surrounding
  642. this TSDU's reception.
  643. ReceiveLength - The length in bytes of client data in the TSDU.
  644. StartingOffset - The offset, in bytes from the beginning of the TSDU,
  645. at which the client data begins.
  646. Tsdu - Pointer to an MDL chain that describes the entire received
  647. Transport Service Data Unit.
  648. TsduDescriptor - A descriptor for the TSDU which must be passed to
  649. TdiReturnChainedReceives in order to return the TSDU for reuse.
  650. Return Value:
  651. NTSTATUS - status of operation.
  652. --*/
  653. {
  654. UNREFERENCED_PARAMETER (TdiEventContext);
  655. UNREFERENCED_PARAMETER (ConnectionContext);
  656. UNREFERENCED_PARAMETER (ReceiveFlags);
  657. UNREFERENCED_PARAMETER (ReceiveLength);
  658. UNREFERENCED_PARAMETER (StartingOffset);
  659. UNREFERENCED_PARAMETER (Tsdu);
  660. UNREFERENCED_PARAMETER (TsduDescriptor);
  661. return STATUS_DATA_NOT_ACCEPTED;
  662. } /* DefaultChainedReceiveHandler */
  663. NTSTATUS
  664. TdiDefaultChainedRcvDatagramHandler(
  665. IN PVOID TdiEventContext,
  666. IN LONG SourceAddressLength,
  667. IN PVOID SourceAddress,
  668. IN LONG OptionsLength,
  669. IN PVOID Options,
  670. IN ULONG ReceiveDatagramFlags,
  671. IN ULONG ReceiveDatagramLength,
  672. IN ULONG StartingOffset,
  673. IN PMDL Tsdu,
  674. IN PVOID TsduDescriptor
  675. )
  676. /*++
  677. Routine Description:
  678. This routine is used as the default chained receive datagram
  679. event handler for the transport endpoint. It is pointed to by
  680. a field in the TP_ENDPOINT structure for an endpoint when the
  681. endpoint is created, and also whenever the TdiSetEventHandler
  682. request is submitted with a NULL EventHandler field.
  683. Arguments:
  684. TdiEventContext - Pointer to the client-provided context value specified
  685. in the TdiSetEventHandler call for TDI_EVENT_CHAINED_RECEIVE_DATAGRAM.
  686. SourceAddressLength - The length of the source network address.
  687. SourceAddress - Pointer to the network address of the source from which
  688. the datagram originated.
  689. OptionsLength - The length of the transport options accompanying this TSDU.
  690. Options - Pointer to the transport options accompanying this TSDU.
  691. ReceiveDatagramFlags - Bitflags which indicate the circumstances
  692. surrounding this TSDU's reception.
  693. ReceiveDatagramLength - The length, in bytes, of the client data in
  694. this TSDU.
  695. StartingOffset - The offset, in bytes from the start of the TSDU, at
  696. which the client data begins.
  697. Tsdu - Pointer to an MDL chain that describes the received Transport
  698. Service Data Unit.
  699. TsduDescriptor - A descriptor for the TSDU which must be passed to
  700. TdiReturnChainedReceives in order to return the TSDU for reuse.
  701. Return Value:
  702. NTSTATUS - status of operation.
  703. --*/
  704. {
  705. UNREFERENCED_PARAMETER (TdiEventContext);
  706. UNREFERENCED_PARAMETER (SourceAddressLength);
  707. UNREFERENCED_PARAMETER (SourceAddress);
  708. UNREFERENCED_PARAMETER (OptionsLength);
  709. UNREFERENCED_PARAMETER (Options);
  710. UNREFERENCED_PARAMETER (ReceiveDatagramLength);
  711. UNREFERENCED_PARAMETER (StartingOffset);
  712. UNREFERENCED_PARAMETER (Tsdu);
  713. UNREFERENCED_PARAMETER (TsduDescriptor);
  714. return STATUS_DATA_NOT_ACCEPTED;
  715. } /* DefaultChainedRcvDatagramHandler */
  716. NTSTATUS
  717. TdiDefaultChainedRcvExpeditedHandler(
  718. IN PVOID TdiEventContext,
  719. IN CONNECTION_CONTEXT ConnectionContext,
  720. IN ULONG ReceiveFlags,
  721. IN ULONG ReceiveLength,
  722. IN ULONG StartingOffset,
  723. IN PMDL Tsdu,
  724. IN PVOID TsduDescriptor
  725. )
  726. /*++
  727. Routine Description:
  728. This routine is used as the default chained expedited receive event
  729. handler for the transport endpoint. It is pointed to by a field
  730. in the TP_ENDPOINT structure for an endpoint when the endpoint is
  731. created, and also whenever the TdiSetEventHandler request is
  732. submitted with a NULL EventHandler field.
  733. Arguments:
  734. TdiEventContext - Pointer to the client-provided context value specified
  735. in the TdiSetEventHandler call for TDI_EVENT_CHAINED_RECEIVE_EXPEDITED.
  736. ConnectionContext - The client-supplied context associated with
  737. the connection on which this connection-oriented TSDU was received.
  738. ReceiveFlags - Bitflags which indicate the circumstances surrounding
  739. this TSDU's reception.
  740. ReceiveLength - The length in bytes of client data in the TSDU.
  741. StartingOffset - The offset, in bytes from the beginning of the TSDU,
  742. at which the client data begins.
  743. Tsdu - Pointer to an MDL chain that describes the entire received
  744. Transport Service Data Unit.
  745. TsduDescriptor - A descriptor for the TSDU which must be passed to
  746. TdiReturnChainedReceives in order to return the TSDU for reuse.
  747. Return Value:
  748. NTSTATUS - status of operation.
  749. --*/
  750. {
  751. UNREFERENCED_PARAMETER (TdiEventContext);
  752. UNREFERENCED_PARAMETER (ConnectionContext);
  753. UNREFERENCED_PARAMETER (ReceiveFlags);
  754. UNREFERENCED_PARAMETER (ReceiveLength);
  755. UNREFERENCED_PARAMETER (StartingOffset);
  756. UNREFERENCED_PARAMETER (Tsdu);
  757. UNREFERENCED_PARAMETER (TsduDescriptor);
  758. return STATUS_DATA_NOT_ACCEPTED;
  759. } /* DefaultRcvExpeditedHandler */
  760. NTSTATUS
  761. TdiDefaultSendPossibleHandler (
  762. IN PVOID TdiEventContext,
  763. IN PVOID ConnectionContext,
  764. IN ULONG BytesAvailable)
  765. /*++
  766. Routine Description:
  767. Arguments:
  768. TdiEventContext - the context value passed in by the user in the Set Event Handler call
  769. ConnectionContext - connection context of connection which can be sent on
  770. BytesAvailable - number of bytes which can now be sent
  771. Return Value:
  772. ignored by the transport
  773. --*/
  774. {
  775. UNREFERENCED_PARAMETER (TdiEventContext);
  776. UNREFERENCED_PARAMETER (ConnectionContext);
  777. UNREFERENCED_PARAMETER (BytesAvailable);
  778. return STATUS_SUCCESS;
  779. }
  780. VOID
  781. TdiBuildNetbiosAddress(
  782. IN PUCHAR NetbiosName,
  783. IN BOOLEAN IsGroupName,
  784. IN OUT PTA_NETBIOS_ADDRESS NetworkName
  785. )
  786. /*++
  787. Routine Description:
  788. This routine builds a TA_NETBIOS_ADDRESS structure in the locations pointed
  789. to by NetworkName. All fields are filled out.
  790. Arguments:
  791. NetbiosName - Pointer to a 16-byte buffer where the a netbios name is
  792. supplied.
  793. IsGroupName - TRUE if this name is a group name, false otherwise.
  794. NetworkName - A pointer to a TA_NETBIOS_ADDRESS structure that is to
  795. receive the buid TDI address.
  796. Return Value:
  797. none.
  798. --*/
  799. {
  800. //IF_TDIDBG (TDI_DEBUG_NAMES) {
  801. // DbgPrint ("TdiBuildNetBIOSAddress: Entered.\n");
  802. //}
  803. NetworkName->TAAddressCount = 1;
  804. NetworkName->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  805. NetworkName->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
  806. if (IsGroupName) {
  807. NetworkName->Address[0].Address[0].NetbiosNameType =
  808. TDI_ADDRESS_NETBIOS_TYPE_GROUP;
  809. } else {
  810. NetworkName->Address[0].Address[0].NetbiosNameType =
  811. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  812. }
  813. RtlCopyMemory (
  814. NetworkName->Address[0].Address[0].NetbiosName,
  815. NetbiosName,
  816. 16);
  817. } /* TdiBuildNetbiosAddress */
  818. NTSTATUS
  819. TdiBuildNetbiosAddressEa (
  820. IN PUCHAR Buffer,
  821. IN BOOLEAN IsGroupName,
  822. IN PUCHAR NetbiosName
  823. )
  824. /*++
  825. Routine Description:
  826. Builds an EA describing a Netbios address in the buffer supplied by the
  827. user.
  828. Arguments:
  829. Buffer - pointer to a buffer that the ea is to be built in. This buffer
  830. must be at least 40 bytes long.
  831. IsGroupName - true if the netbios name is a group name, false otherwise.
  832. NetbiosName - the netbios name to be inserted in the EA to be built.
  833. Return Value:
  834. An informative error code if something goes wrong. STATUS_SUCCESS if the
  835. ea is built properly.
  836. --*/
  837. {
  838. PFILE_FULL_EA_INFORMATION EaBuffer;
  839. PTA_NETBIOS_ADDRESS TAAddress;
  840. ULONG Length;
  841. IF_TDIDBG (TDI_DEBUG_NAMES) {
  842. DbgPrint ("TdiBuildNetbiosAddressEa: Entered\n ");
  843. }
  844. try {
  845. Length = FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0] ) +
  846. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  847. sizeof (TA_NETBIOS_ADDRESS);
  848. EaBuffer = (PFILE_FULL_EA_INFORMATION)Buffer;
  849. if (EaBuffer == NULL) {
  850. return STATUS_UNSUCCESSFUL;
  851. }
  852. EaBuffer->NextEntryOffset = 0;
  853. EaBuffer->Flags = 0;
  854. EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  855. EaBuffer->EaValueLength = sizeof (TA_NETBIOS_ADDRESS);
  856. RtlCopyMemory (
  857. EaBuffer->EaName,
  858. TdiTransportAddress,
  859. EaBuffer->EaNameLength + 1);
  860. TAAddress = (PTA_NETBIOS_ADDRESS)&EaBuffer->EaName[EaBuffer->EaNameLength+1];
  861. TdiBuildNetbiosAddress (
  862. NetbiosName,
  863. IsGroupName,
  864. TAAddress);
  865. } except(EXCEPTION_EXECUTE_HANDLER) {
  866. //
  867. // Couldn't touch the passed parameters; just return an error
  868. // status.
  869. //
  870. return GetExceptionCode();
  871. }
  872. return STATUS_SUCCESS;
  873. } /* TdiBuildNetbiosAddressEa */
  874. NTSTATUS
  875. TdiCopyMdlToBuffer(
  876. IN PMDL SourceMdlChain,
  877. IN ULONG SourceOffset,
  878. IN PVOID DestinationBuffer,
  879. IN ULONG DestinationOffset,
  880. IN ULONG DestinationBufferSize,
  881. OUT PULONG BytesCopied
  882. )
  883. /*++
  884. Routine Description:
  885. This routine copies data described by the source MDL chain starting at
  886. the source offset, into a flat buffer specified by the SVA starting at
  887. the destination offset. A maximum of DestinationBufferSize bytes can
  888. be copied. The actual number of bytes copied is returned in BytesCopied.
  889. Arguments:
  890. SourceMdlChain - Pointer to a chain of MDLs describing the source data.
  891. SourceOffset - Number of bytes to skip in the source data.
  892. DestinationBuffer - Pointer to a flat buffer to copy the data to.
  893. DestinationOffset - Number of leading bytes to skip in the destination buffer.
  894. DestinationBufferSize - Size of the output buffer, including the offset.
  895. BytesCopied - Pointer to a longword where the actual number of bytes
  896. transferred will be returned.
  897. Return Value:
  898. NTSTATUS - status of operation.
  899. --*/
  900. {
  901. PUCHAR Dest, Src;
  902. ULONG SrcBytesLeft, DestBytesLeft, BytesSkipped=0;
  903. // IF_TDIDBG (TDI_DEBUG_MAP) {
  904. // DbgPrint ("TdiCopyMdlToBuffer: Entered.\n");
  905. // }
  906. ASSERT( DestinationBufferSize >= DestinationOffset );
  907. *BytesCopied = 0;
  908. //
  909. // Skip source bytes.
  910. //
  911. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  912. return STATUS_INSUFFICIENT_RESOURCES;
  913. }
  914. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  915. while (BytesSkipped < SourceOffset) {
  916. if (SrcBytesLeft > (SourceOffset - BytesSkipped)) {
  917. // PANIC ("TdiCopyMdlToBuffer: Skipping part of this MDL.\n");
  918. SrcBytesLeft -= (SourceOffset - BytesSkipped);
  919. Src += (SourceOffset - BytesSkipped);
  920. BytesSkipped = SourceOffset;
  921. break;
  922. } else if (SrcBytesLeft == (SourceOffset - BytesSkipped)) {
  923. // PANIC ("TdiCopyMdlToBuffer: Skipping this exact MDL.\n");
  924. SourceMdlChain = SourceMdlChain->Next;
  925. if (SourceMdlChain == NULL) {
  926. //PANIC ("TdiCopyMdlToBuffer: MDL chain was all header.\n");
  927. return STATUS_SUCCESS; // no bytes copied.
  928. }
  929. BytesSkipped = SourceOffset;
  930. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  931. return STATUS_INSUFFICIENT_RESOURCES;
  932. }
  933. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  934. break;
  935. } else {
  936. // PANIC ("TdiCopyMdlToBuffer: Skipping all of this MDL & more.\n");
  937. BytesSkipped += SrcBytesLeft;
  938. SourceMdlChain = SourceMdlChain->Next;
  939. if (SourceMdlChain == NULL) {
  940. //PANIC ("TdiCopyMdlToBuffer: Premature end of MDL chain.\n");
  941. return STATUS_SUCCESS; // no bytes copied.
  942. }
  943. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  944. return STATUS_INSUFFICIENT_RESOURCES;
  945. }
  946. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  947. }
  948. }
  949. // PANIC ("TdiCopyMdlToBuffer: done skipping source bytes.\n");
  950. //
  951. // Skip destination bytes.
  952. //
  953. Dest = (PUCHAR)DestinationBuffer + DestinationOffset;
  954. DestBytesLeft = DestinationBufferSize - DestinationOffset;
  955. //
  956. // Copy source data into the destination buffer until it's full or
  957. // we run out of data, whichever comes first.
  958. //
  959. while (DestBytesLeft && SourceMdlChain) {
  960. if (SrcBytesLeft == 0) {
  961. // PANIC ("TdiCopyMdlToBuffer: MDL is empty, skipping to next one.\n");
  962. SourceMdlChain = SourceMdlChain->Next;
  963. if (SourceMdlChain == NULL) {
  964. // PANIC ("TdiCopyMdlToBuffer: But there are no more MDLs.\n");
  965. return STATUS_SUCCESS;
  966. }
  967. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  968. return STATUS_INSUFFICIENT_RESOURCES;
  969. }
  970. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  971. continue; // skip 0-length MDL's.
  972. }
  973. // PANIC ("TdiCopyMdlToBuffer: Copying a chunk.\n");
  974. if (DestBytesLeft == SrcBytesLeft) {
  975. // PANIC ("TdiCopyMdlToBuffer: Copying exact amount.\n");
  976. RtlCopyBytes (Dest, Src, DestBytesLeft);
  977. *BytesCopied += DestBytesLeft;
  978. return STATUS_SUCCESS;
  979. } else if (DestBytesLeft < SrcBytesLeft) {
  980. // PANIC ("TdiCopyMdlToBuffer: Buffer overflow, copying some.\n");
  981. RtlCopyBytes (Dest, Src, DestBytesLeft);
  982. *BytesCopied += DestBytesLeft;
  983. return STATUS_BUFFER_OVERFLOW;
  984. } else {
  985. // PANIC ("TdiCopyMdlToBuffer: Copying all of this MDL, & more.\n");
  986. RtlCopyBytes (Dest, Src, SrcBytesLeft);
  987. *BytesCopied += SrcBytesLeft;
  988. DestBytesLeft -= SrcBytesLeft;
  989. Dest += SrcBytesLeft;
  990. SrcBytesLeft = 0;
  991. }
  992. }
  993. return SourceMdlChain == NULL ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW;
  994. } /* TdiCopyMdlToBuffer */
  995. NTSTATUS
  996. TdiCopyBufferToMdl (
  997. IN PVOID SourceBuffer,
  998. IN ULONG SourceOffset,
  999. IN ULONG SourceBytesToCopy,
  1000. IN PMDL DestinationMdlChain,
  1001. IN ULONG DestinationOffset,
  1002. IN PULONG BytesCopied
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine copies data described by the source buffer to the MDL chain
  1007. described by the DestinationMdlChain. The
  1008. Arguments:
  1009. SourceBuffer - pointer to the source buffer
  1010. SourceOffset - Number of bytes to skip in the source data.
  1011. SourceBytesToCopy - number of bytes to copy from the source buffer
  1012. DestinationMdlChain - Pointer to a chain of MDLs describing the
  1013. destination buffers.
  1014. DestinationOffset - Number of bytes to skip in the destination data.
  1015. BytesCopied - Pointer to a longword where the actual number of bytes
  1016. transferred will be returned.
  1017. Return Value:
  1018. NTSTATUS - status of operation.
  1019. --*/
  1020. {
  1021. PUCHAR Dest, Src;
  1022. ULONG DestBytesLeft, BytesSkipped=0;
  1023. //IF_TDIDBG (TDI_DEBUG_MAP) {
  1024. // DbgPrint ("TdiCopyBufferToMdl: Entered.\n");
  1025. //}
  1026. *BytesCopied = 0;
  1027. if (SourceBytesToCopy == 0) {
  1028. return STATUS_SUCCESS;
  1029. }
  1030. if (DestinationMdlChain == NULL) {
  1031. // No MDL to copy to. Output buffer was zero length.
  1032. return STATUS_BUFFER_OVERFLOW;
  1033. }
  1034. //
  1035. // Skip Destination bytes.
  1036. //
  1037. if ((Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority)) == NULL) {
  1038. return STATUS_INSUFFICIENT_RESOURCES;
  1039. }
  1040. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1041. while (BytesSkipped < DestinationOffset) {
  1042. if (DestBytesLeft > (DestinationOffset - BytesSkipped)) {
  1043. // PANIC ("TdiCopyMdlToBuffer: Skipping part of this MDL.\n");
  1044. DestBytesLeft -= (DestinationOffset - BytesSkipped);
  1045. Dest += (DestinationOffset - BytesSkipped);
  1046. BytesSkipped = DestinationOffset;
  1047. break;
  1048. } else if (DestBytesLeft == (DestinationOffset - BytesSkipped)) {
  1049. // PANIC ("TdiCopyMdlToBuffer: Skipping this exact MDL.\n");
  1050. DestinationMdlChain = DestinationMdlChain->Next;
  1051. if (DestinationMdlChain == NULL) {
  1052. //PANIC ("TdiCopyMdlToBuffer: MDL chain was all header.\n");
  1053. return STATUS_BUFFER_OVERFLOW; // no bytes copied.
  1054. }
  1055. BytesSkipped = DestinationOffset;
  1056. if ((Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority)) == NULL) {
  1057. return STATUS_INSUFFICIENT_RESOURCES;
  1058. }
  1059. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1060. break;
  1061. } else {
  1062. // PANIC ("TdiCopyMdlToBuffer: Skipping all of this MDL & more.\n");
  1063. BytesSkipped += DestBytesLeft;
  1064. DestinationMdlChain = DestinationMdlChain->Next;
  1065. if (DestinationMdlChain == NULL) {
  1066. //PANIC ("TdiCopyMdlToBuffer: Premature end of MDL chain.\n");
  1067. return STATUS_BUFFER_OVERFLOW; // no bytes copied.
  1068. }
  1069. if ((Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority)) == NULL) {
  1070. return STATUS_INSUFFICIENT_RESOURCES;
  1071. }
  1072. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1073. }
  1074. }
  1075. // PANIC ("TdiCopyMdlToBuffer: done skipping source bytes.\n");
  1076. //
  1077. // Skip source bytes.
  1078. //
  1079. Src = (PUCHAR)SourceBuffer + SourceOffset;
  1080. //
  1081. // Copy source data into the destination buffer until it's full or
  1082. // we run out of data, whichever comes first.
  1083. //
  1084. while ((SourceBytesToCopy != 0) && (DestinationMdlChain != NULL)) {
  1085. if (DestBytesLeft == 0) {
  1086. // PANIC ("TdiCopyMdlToBuffer: MDL is empty, skipping to next one.\n");
  1087. DestinationMdlChain = DestinationMdlChain->Next;
  1088. if (DestinationMdlChain == NULL) {
  1089. // PANIC ("TdiCopyMdlToBuffer: But there are no more MDLs.\n");
  1090. return STATUS_BUFFER_OVERFLOW;
  1091. }
  1092. Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority);
  1093. if (Dest == NULL) {
  1094. return STATUS_BUFFER_OVERFLOW;
  1095. }
  1096. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1097. continue; // skip 0-length MDL's.
  1098. }
  1099. // PANIC ("TdiCopyMdlToBuffer: Copying a chunk.\n");
  1100. if (DestBytesLeft >= SourceBytesToCopy) {
  1101. // PANIC ("TdiCopyMdlToBuffer: Copying exact amount.\n");
  1102. RtlCopyBytes (Dest, Src, SourceBytesToCopy);
  1103. *BytesCopied += SourceBytesToCopy;
  1104. return STATUS_SUCCESS;
  1105. } else {
  1106. // PANIC ("TdiCopyMdlToBuffer: Copying all of this MDL, & more.\n");
  1107. RtlCopyBytes (Dest, Src, DestBytesLeft);
  1108. *BytesCopied += DestBytesLeft;
  1109. SourceBytesToCopy -= DestBytesLeft;
  1110. Src += DestBytesLeft;
  1111. DestBytesLeft = 0;
  1112. }
  1113. }
  1114. return SourceBytesToCopy == 0 ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW;
  1115. } /* TdiCopyBufferToMdl */
  1116. NTSTATUS
  1117. TdiCopyMdlChainToMdlChain (
  1118. IN PMDL SourceMdlChain,
  1119. IN ULONG SourceOffset,
  1120. IN PMDL DestinationMdlChain,
  1121. IN ULONG DestinationOffset,
  1122. OUT PULONG BytesCopied
  1123. )
  1124. /*++
  1125. Routine Description:
  1126. This routine copies data described by the source MDL chain to the MDL chain
  1127. described by the DestinationMdlChain.
  1128. Arguments:
  1129. SourceMdlChain - Pointer to a chain of MDLs describing the source buffers.
  1130. SourceOffset - Number of initial bytes to skip in the source data.
  1131. DestinationMdlChain - Pointer to a chain of MDLs describing the
  1132. destination buffers.
  1133. DestinationOffset - Number of initial bytes to skip in the destination data.
  1134. BytesCopied - Pointer to a longword where the actual number of bytes
  1135. transferred will be returned.
  1136. Return Value:
  1137. NTSTATUS - status of operation.
  1138. --*/
  1139. {
  1140. PUCHAR Dest, Src;
  1141. ULONG DestBytesLeft, SrcBytesLeft, BytesSkipped;
  1142. ULONG CopyAmount;
  1143. *BytesCopied = 0;
  1144. if (DestinationMdlChain == NULL) {
  1145. // No MDL to copy to.
  1146. return STATUS_BUFFER_OVERFLOW;
  1147. }
  1148. //
  1149. // Skip Destination bytes.
  1150. //
  1151. BytesSkipped = 0;
  1152. if ((Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority)) == NULL) {
  1153. return STATUS_INSUFFICIENT_RESOURCES;
  1154. }
  1155. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1156. while (BytesSkipped < DestinationOffset) {
  1157. if (DestBytesLeft > (DestinationOffset - BytesSkipped)) {
  1158. // the desired offset resides within this MDL.
  1159. Dest += (DestinationOffset - BytesSkipped);
  1160. DestBytesLeft -= (DestinationOffset - BytesSkipped);
  1161. break;
  1162. }
  1163. // skip over this MDL
  1164. BytesSkipped += DestBytesLeft;
  1165. DestinationMdlChain = DestinationMdlChain->Next;
  1166. if (DestinationMdlChain == NULL) {
  1167. return STATUS_BUFFER_OVERFLOW;
  1168. }
  1169. if ((Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority)) == NULL) {
  1170. return STATUS_INSUFFICIENT_RESOURCES;
  1171. }
  1172. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1173. }
  1174. //
  1175. // Skip source bytes.
  1176. //
  1177. BytesSkipped = 0;
  1178. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  1179. return STATUS_INSUFFICIENT_RESOURCES;
  1180. }
  1181. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  1182. while (BytesSkipped < SourceOffset) {
  1183. if (SrcBytesLeft > (SourceOffset - BytesSkipped)) {
  1184. // the desired offset resides within this MDL.
  1185. Src += (SourceOffset - BytesSkipped);
  1186. SrcBytesLeft -= (SourceOffset - BytesSkipped);
  1187. break;
  1188. }
  1189. // skip over this MDL
  1190. BytesSkipped += SrcBytesLeft;
  1191. SourceMdlChain = SourceMdlChain->Next;
  1192. if (SourceMdlChain == NULL) {
  1193. return STATUS_BUFFER_OVERFLOW;
  1194. }
  1195. if ((Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority)) == NULL) {
  1196. return STATUS_INSUFFICIENT_RESOURCES;
  1197. }
  1198. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  1199. }
  1200. //
  1201. // Copy source data into the destination buffer until it's full or
  1202. // we run out of data, whichever comes first.
  1203. //
  1204. while ((SourceMdlChain != NULL) && (DestinationMdlChain != NULL)) {
  1205. if (SrcBytesLeft == 0)
  1206. {
  1207. SourceMdlChain = SourceMdlChain->Next;
  1208. if (SourceMdlChain == NULL) {
  1209. return STATUS_SUCCESS;
  1210. }
  1211. Src = MmGetSystemAddressForMdlSafe (SourceMdlChain, NormalPagePriority);
  1212. if (Src == NULL) {
  1213. return STATUS_INSUFFICIENT_RESOURCES;
  1214. }
  1215. SrcBytesLeft = MmGetMdlByteCount (SourceMdlChain);
  1216. continue;
  1217. }
  1218. if (DestBytesLeft == 0) {
  1219. DestinationMdlChain = DestinationMdlChain->Next;
  1220. if (DestinationMdlChain == NULL) {
  1221. return STATUS_BUFFER_OVERFLOW;
  1222. }
  1223. Dest = MmGetSystemAddressForMdlSafe (DestinationMdlChain, NormalPagePriority);
  1224. if (Dest == NULL) {
  1225. return STATUS_BUFFER_OVERFLOW;
  1226. }
  1227. DestBytesLeft = MmGetMdlByteCount (DestinationMdlChain);
  1228. continue;
  1229. }
  1230. CopyAmount = ((DestBytesLeft > SrcBytesLeft)? SrcBytesLeft: DestBytesLeft);
  1231. RtlCopyBytes (Dest, Src, CopyAmount);
  1232. SrcBytesLeft -= CopyAmount;
  1233. Src += CopyAmount;
  1234. DestBytesLeft -= CopyAmount;
  1235. Dest += CopyAmount;
  1236. *BytesCopied += CopyAmount;
  1237. }
  1238. return SourceMdlChain == NULL ? STATUS_SUCCESS : STATUS_BUFFER_OVERFLOW;
  1239. } /* TdiCopyMdlChainToMdlChain */
  1240. NTSTATUS
  1241. TdiOpenNetbiosAddress (
  1242. IN OUT PHANDLE FileHandle,
  1243. IN PUCHAR Buffer,
  1244. IN PVOID DeviceName,
  1245. IN PVOID Address)
  1246. /*++
  1247. Routine Description:
  1248. Opens an address on the given file handle and device.
  1249. Arguments:
  1250. FileHandle - the returned handle to the file object that is opened.
  1251. Buffer - pointer to a buffer that the ea is to be built in. This buffer
  1252. must be at least 40 bytes long.
  1253. DeviceName - the Unicode string that points to the device object.
  1254. Name - the address to be registered. If this pointer is NULL, the routine
  1255. will attempt to open a "control channel" to the device; that is, it
  1256. will attempt to open the file object with a null ea pointer, and if the
  1257. transport provider allows for that, will return that handle.
  1258. Return Value:
  1259. An informative error code if something goes wrong. STATUS_SUCCESS if the
  1260. returned file handle is valid.
  1261. --*/
  1262. {
  1263. IO_STATUS_BLOCK IoStatusBlock;
  1264. NTSTATUS Status;
  1265. OBJECT_ATTRIBUTES ObjectAttributes;
  1266. PFILE_FULL_EA_INFORMATION EaBuffer;
  1267. TA_NETBIOS_ADDRESS NetbiosAddress;
  1268. PSZ Name;
  1269. ULONG Length;
  1270. IF_TDIDBG (TDI_DEBUG_NAMES) {
  1271. DbgPrint ("TdiOpenNetbiosAddress: Opening ");
  1272. if (Address == NULL) {
  1273. DbgPrint (" Control Channel");
  1274. } else {
  1275. DbgPrint (Address);
  1276. }
  1277. DbgPrint (".\n");
  1278. }
  1279. if (Address != NULL) {
  1280. Name = (PSZ)Address;
  1281. try {
  1282. Length = FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0] ) +
  1283. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  1284. sizeof(TA_NETBIOS_ADDRESS);
  1285. EaBuffer = (PFILE_FULL_EA_INFORMATION)Buffer;
  1286. if (EaBuffer == NULL) {
  1287. return STATUS_UNSUCCESSFUL;
  1288. }
  1289. EaBuffer->NextEntryOffset = 0;
  1290. EaBuffer->Flags = 0;
  1291. EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  1292. EaBuffer->EaValueLength = sizeof (TA_NETBIOS_ADDRESS);
  1293. RtlCopyMemory(
  1294. EaBuffer->EaName,
  1295. TdiTransportAddress,
  1296. EaBuffer->EaNameLength + 1
  1297. );
  1298. //
  1299. // Create a copy of the NETBIOS address descriptor in a local
  1300. // first, in order to avoid alignment problems.
  1301. //
  1302. NetbiosAddress.TAAddressCount = 1;
  1303. NetbiosAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  1304. NetbiosAddress.Address[0].AddressLength =
  1305. sizeof (TDI_ADDRESS_NETBIOS);
  1306. NetbiosAddress.Address[0].Address[0].NetbiosNameType =
  1307. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  1308. RtlCopyMemory(
  1309. NetbiosAddress.Address[0].Address[0].NetbiosName,
  1310. Name,
  1311. 16
  1312. );
  1313. RtlCopyMemory (
  1314. &EaBuffer->EaName[EaBuffer->EaNameLength + 1],
  1315. &NetbiosAddress,
  1316. sizeof(TA_NETBIOS_ADDRESS)
  1317. );
  1318. } except(EXCEPTION_EXECUTE_HANDLER) {
  1319. //
  1320. // Couldn't touch the passed parameters; just return an error
  1321. // status.
  1322. //
  1323. return GetExceptionCode();
  1324. }
  1325. } else {
  1326. EaBuffer = NULL;
  1327. Length = 0;
  1328. }
  1329. InitializeObjectAttributes (
  1330. &ObjectAttributes,
  1331. DeviceName,
  1332. OBJ_CASE_INSENSITIVE,
  1333. NULL,
  1334. NULL);
  1335. Status = NtCreateFile (
  1336. FileHandle,
  1337. FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, // desired access.
  1338. &ObjectAttributes, // object attributes.
  1339. &IoStatusBlock, // returned status information.
  1340. 0, // block size (unused).
  1341. 0, // file attributes.
  1342. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access.
  1343. FILE_CREATE, // create disposition.
  1344. 0, // create options.
  1345. EaBuffer, // EA buffer.
  1346. Length); // EA length.
  1347. if (!NT_SUCCESS( Status )) {
  1348. IF_TDIDBG (TDI_DEBUG_NAMES) {
  1349. DbgPrint ("TdiOpenNetbiosEndpoint: FAILURE, NtCreateFile returned status %lx.\n", Status);
  1350. }
  1351. return Status;
  1352. }
  1353. Status = IoStatusBlock.Status;
  1354. if (!(NT_SUCCESS( Status ))) {
  1355. IF_TDIDBG (TDI_DEBUG_NAMES) {
  1356. DbgPrint ("TdiOpenNetbiosEndpoint: FAILURE, IoStatusBlock.Status contains status code=%lx.\n", Status);
  1357. }
  1358. }
  1359. return Status;
  1360. } /* TdiOpenNetbiosAddress */
  1361. VOID
  1362. TdiReturnChainedReceives(
  1363. IN PVOID *TsduDescriptors,
  1364. IN ULONG NumberOfTsdus
  1365. )
  1366. /*++
  1367. Routine Description:
  1368. Used by a TDI client to return ownership of a set of chained receive TSDUs
  1369. to the NDIS layer. This routine may only be called if the client took
  1370. ownership of the TSDUs by returning STATUS_PENDING to one of the
  1371. CHAINED_RECEIVE indications.
  1372. Arguments:
  1373. TsduDescriptors - An array of TSDU descriptors. Each descriptor was
  1374. provided in one of the CHAINED_RECEIVE indications. The descriptors
  1375. are actually pointers to the NDIS_PACKETS containing the TSDUs.
  1376. NumberOfTsdus - The count of TSDU descriptors in the TsduDescriptors array.
  1377. Return Value:
  1378. None.
  1379. --*/
  1380. {
  1381. NdisReturnPackets(
  1382. (PNDIS_PACKET *) TsduDescriptors,
  1383. (UINT) NumberOfTsdus
  1384. );
  1385. }
  1386. VOID
  1387. TdiInitialize(
  1388. VOID
  1389. )
  1390. /*++
  1391. Routine Description:
  1392. The TDI initialization routine, since our DriverEntry isn't called.
  1393. If we're not already initialized we'll initialize our lists heads.
  1394. Arguments:
  1395. Nothing.
  1396. Return Value:
  1397. None.
  1398. --*/
  1399. {
  1400. // See if we're already initialized. If we're not,
  1401. // we won't have an initalized spinlock so we can't use that
  1402. // to serialize this. Instead, we interlocked increment a counter
  1403. // that is initially 0. If the counter goes to 1, we're the
  1404. // first one through here, so we'll do the initialization. Otherwise
  1405. // it's already been done, so we'll decrement the counter back
  1406. // to it's original state.
  1407. if (InterlockedIncrement(&TdiInitializationCount) == 1) {
  1408. // We're the first ones.
  1409. // Initialize the variables the register/deregister code uses.
  1410. KeInitializeSpinLock(&TDIListLock);
  1411. InitializeListHead(&PnpHandlerClientList);
  1412. InitializeListHead(&PnpHandlerProviderList);
  1413. InitializeListHead(&PnpHandlerRequestList);
  1414. NdisRegisterTdiCallBack(TdiRegisterDeviceObject, TdiPnPHandler);
  1415. #if DBG
  1416. //
  1417. // If a debug build store a limited number of messages.
  1418. //
  1419. DbgMsgInit();
  1420. #endif
  1421. } else {
  1422. // Already been done, just decrement the counter.
  1423. InterlockedDecrement(&TdiInitializationCount);
  1424. }
  1425. }