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.

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