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.

1149 lines
34 KiB

  1. /////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // open.cpp
  7. //
  8. // Abstract:
  9. // This module contains code which deals with opening and closing
  10. // of the various types of tdi objects
  11. //
  12. //////////////////////////////////////////////////////////
  13. #include "sysvars.h"
  14. extern "C"
  15. {
  16. #pragma warning(disable: NAMELESS_STRUCT_UNION)
  17. #include "tdiinfo.h"
  18. #pragma warning(default: NAMELESS_STRUCT_UNION)
  19. }
  20. //
  21. // defines stolen from include files not in ddk
  22. //
  23. #define AO_OPTION_IP_UCASTIF 17
  24. #define FSCTL_TCP_BASE FILE_DEVICE_NETWORK
  25. #define _TCP_CTL_CODE(function, method, access) \
  26. CTL_CODE(FSCTL_TCP_BASE, function, method, access)
  27. #define IOCTL_TCP_WSH_SET_INFORMATION_EX \
  28. _TCP_CTL_CODE(10, METHOD_BUFFERED, FILE_ANY_ACCESS)
  29. //
  30. // end of stolen defines
  31. //
  32. //////////////////////////////////////////////////////////////
  33. // private constants and prototypes
  34. //////////////////////////////////////////////////////////////
  35. const PCHAR strFunc1 = "TSOpenControl";
  36. const PCHAR strFunc2 = "TSCloseControl";
  37. const PCHAR strFunc3 = "TSOpenAddress";
  38. const PCHAR strFunc4 = "TSCloseAddress";
  39. const PCHAR strFunc5 = "TSOpenEndpoint";
  40. const PCHAR strFunc6 = "TSCloseEndpoint";
  41. //const PCHAR strFuncP1 = "TSCompleteCommand";
  42. const PCHAR strFuncP2 = "TSPerformOpenControl";
  43. const PCHAR strFuncP3 = "TSPerformOpenAddress";
  44. const PCHAR strFuncP4 = "TSPerformOpenEndpoint";
  45. const PCHAR strFuncP5 = "TSPerformAssociate";
  46. const PCHAR strFuncP6 = "TSPerformDisassociate";
  47. TDI_STATUS
  48. TSCompleteCommand(
  49. PDEVICE_OBJECT pDeviceObject,
  50. PIRP pLowerIrp,
  51. PVOID pvContext
  52. );
  53. NTSTATUS
  54. TSPerformOpenControl(
  55. PCONTROL_CHANNEL pControlChannel,
  56. PUCNTSTRING pucString
  57. );
  58. NTSTATUS
  59. TSPerformOpenAddress(
  60. PADDRESS_OBJECT pAddressObject,
  61. PUCNTSTRING pucString,
  62. PTRANSPORT_ADDRESS pTransportAddress,
  63. BOOLEAN fIsConnect
  64. );
  65. NTSTATUS
  66. TSPerformOpenEndpoint(
  67. PENDPOINT_OBJECT pEndpointObject,
  68. PUCNTSTRING pucString
  69. );
  70. NTSTATUS
  71. TSPerformAssociate(
  72. PENDPOINT_OBJECT pEndpoint
  73. );
  74. VOID
  75. TSPerformDisassociate(
  76. PENDPOINT_OBJECT pEndpoint
  77. );
  78. //////////////////////////////////////////////////////////////
  79. // public functions
  80. //////////////////////////////////////////////////////////////
  81. // ----------------------------------------------------------------------------
  82. //
  83. // Function: TSOpenControl
  84. //
  85. // Arguments: pSendBuffer -- arguments from user dll for open command
  86. // pIrp -- completion information
  87. //
  88. // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
  89. //
  90. // Descript: This function sets up the structure for a new control channel,
  91. // and attempts to open the specified control channel
  92. //
  93. // ----------------------------------------------------------------------------
  94. NTSTATUS
  95. TSOpenControl(PSEND_BUFFER pSendBuffer,
  96. PRECEIVE_BUFFER pReceiveBuffer)
  97. {
  98. PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
  99. //
  100. // show debug, if it is turned on
  101. //
  102. if (ulDebugLevel & ulDebugShowCommand)
  103. {
  104. DebugPrint1("\nCommand = ulOPENCONTROL\n"
  105. "DeviceName = %ws\n",
  106. pucString->wcBuffer);
  107. }
  108. //
  109. // allocate our structure and put it in the linked list...
  110. //
  111. PCONTROL_CHANNEL pControlChannel;
  112. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pControlChannel,
  113. sizeof(CONTROL_CHANNEL),
  114. strFunc1,
  115. "ControlChannel");
  116. if (lStatus == STATUS_SUCCESS)
  117. {
  118. pControlChannel->GenHead.ulSignature = ulControlChannelObject;
  119. ULONG ulTdiHandle = TSInsertNode(&pControlChannel->GenHead);
  120. if (ulTdiHandle)
  121. {
  122. lStatus = TSPerformOpenControl(pControlChannel, pucString);
  123. if (lStatus == STATUS_SUCCESS)
  124. {
  125. pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
  126. return STATUS_SUCCESS;
  127. }
  128. //
  129. // handle errors in PerformOpenControl
  130. //
  131. TSRemoveNode(ulTdiHandle);
  132. }
  133. else
  134. {
  135. lStatus = STATUS_INSUFFICIENT_RESOURCES;
  136. }
  137. TSFreeMemory(pControlChannel);
  138. }
  139. return lStatus;
  140. }
  141. // -----------------------------------------------------------------
  142. //
  143. // Function: TSCloseControl
  144. //
  145. // Arguments: pControlChannel -- our control channel object to close
  146. //
  147. // Returns: none
  148. //
  149. // Descript: This function frees the resources for a control channel,
  150. // and calls the tdi provider to close it
  151. //
  152. // ----------------------------------------------------------------------------
  153. VOID
  154. TSCloseControl(PCONTROL_CHANNEL pControlChannel)
  155. {
  156. //
  157. // show debug, if it is turned on
  158. //
  159. if (ulDebugLevel & ulDebugShowCommand)
  160. {
  161. DebugPrint1("\nCommand = ulCLOSECONTROL\n"
  162. "ControlChannel = %p\n",
  163. pControlChannel);
  164. }
  165. ObDereferenceObject(pControlChannel->GenHead.pFileObject);
  166. NTSTATUS lStatus = ZwClose(pControlChannel->GenHead.FileHandle);
  167. if (lStatus != STATUS_SUCCESS)
  168. {
  169. DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
  170. strFunc2,
  171. lStatus);
  172. }
  173. TSFreeMemory(pControlChannel);
  174. }
  175. // -----------------------------------------------------------------
  176. //
  177. // Function: TSOpenAddress
  178. //
  179. // Arguments: pSendBuffer -- arguments from user dll for open command
  180. // pIrp -- completion information
  181. //
  182. // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
  183. //
  184. // Descript: This function sets up the structure for a new address object,
  185. // and attempts to open the specified address object
  186. //
  187. // ----------------------------------------------------------------------------
  188. NTSTATUS
  189. TSOpenAddress(PSEND_BUFFER pSendBuffer,
  190. PRECEIVE_BUFFER pReceiveBuffer)
  191. {
  192. PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
  193. PTRANSPORT_ADDRESS pTransportAddress
  194. = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr;
  195. //
  196. // show debug, if it is turned on
  197. //
  198. if (ulDebugLevel & ulDebugShowCommand)
  199. {
  200. DebugPrint1("\nCommand = ulOPENADDRESS\n"
  201. "DeviceName = %ws\n",
  202. pucString->wcBuffer);
  203. TSPrintTaAddress(pTransportAddress->Address);
  204. }
  205. //
  206. // allocate our structure and put it in the linked list...
  207. //
  208. PADDRESS_OBJECT pAddressObject;
  209. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pAddressObject,
  210. sizeof(ADDRESS_OBJECT),
  211. strFunc3,
  212. "AddressObject");
  213. if (lStatus == STATUS_SUCCESS)
  214. {
  215. pAddressObject->GenHead.ulSignature = ulAddressObject;
  216. ULONG ulTdiHandle = TSInsertNode(&pAddressObject->GenHead);
  217. if (ulTdiHandle)
  218. {
  219. lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, FALSE);
  220. if (lStatus == STATUS_SUCCESS)
  221. {
  222. pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
  223. return STATUS_SUCCESS;
  224. }
  225. //
  226. // handle error in PerformOpenAddress
  227. //
  228. TSRemoveNode(ulTdiHandle);
  229. }
  230. else
  231. {
  232. lStatus = STATUS_INSUFFICIENT_RESOURCES;
  233. }
  234. TSFreeMemory(pAddressObject);
  235. }
  236. return lStatus;
  237. }
  238. // -----------------------------------------------------------------
  239. //
  240. // Function: TSCloseAddress
  241. //
  242. // Arguments: pAddressObject -- address object to close
  243. //
  244. // Returns: none
  245. //
  246. // Descript: This function frees the resources for an address object,
  247. // and calls the tdi provider to close it
  248. //
  249. // ----------------------------------------------------------------------------
  250. VOID
  251. TSCloseAddress(PADDRESS_OBJECT pAddressObject)
  252. {
  253. //
  254. // show debug, if it is turned on
  255. //
  256. if (ulDebugLevel & ulDebugShowCommand)
  257. {
  258. DebugPrint1("\nCommand = ulCLOSEADDRESS\n"
  259. "AddressObject = %p\n",
  260. pAddressObject);
  261. }
  262. TSFreeSpinLock(&pAddressObject->TdiSpinLock);
  263. TSFreePacketData(pAddressObject);
  264. ObDereferenceObject(pAddressObject->GenHead.pFileObject);
  265. if (pAddressObject->pIrpPool)
  266. {
  267. TSFreeIrpPool(pAddressObject->pIrpPool);
  268. }
  269. NTSTATUS lStatus = ZwClose(pAddressObject->GenHead.FileHandle);
  270. if (lStatus != STATUS_SUCCESS)
  271. {
  272. DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
  273. strFunc4,
  274. lStatus);
  275. }
  276. TSFreeMemory(pAddressObject);
  277. }
  278. // -----------------------------------------------------------------
  279. //
  280. // Function: TSOpenEndpoint
  281. //
  282. // Arguments: pSendBuffer -- arguments from user dll for open command
  283. // pIrp -- completion information
  284. //
  285. // Returns: Final status of the open (STATUS_SUCCESSFUL or STATUS_errorcode)
  286. //
  287. // Descript: This function sets up the structure for an endpoint. This
  288. // involves opening an endpoint, opening an address object, and
  289. // associating them...
  290. //
  291. // ----------------------------------------------------------------------------
  292. NTSTATUS
  293. TSOpenEndpoint(PSEND_BUFFER pSendBuffer,
  294. PRECEIVE_BUFFER pReceiveBuffer)
  295. {
  296. PUCNTSTRING pucString = &pSendBuffer->COMMAND_ARGS.OpenArgs.ucsDeviceName;
  297. PTRANSPORT_ADDRESS pTransportAddress
  298. = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.OpenArgs.TransAddr;
  299. //
  300. // show debug, if it is turned on
  301. //
  302. if (ulDebugLevel & ulDebugShowCommand)
  303. {
  304. DebugPrint1("\nCommand = ulOPENENDPOINT\n"
  305. "DeviceName = %ws\n",
  306. pucString->wcBuffer);
  307. TSPrintTaAddress(pTransportAddress->Address);
  308. }
  309. //
  310. // set up for the file open
  311. // need to do our "context" structure first, since the
  312. // eabuffer requires it...
  313. //
  314. PENDPOINT_OBJECT pEndpoint;
  315. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&pEndpoint,
  316. sizeof(ENDPOINT_OBJECT),
  317. strFunc5,
  318. "EndpointObject");
  319. if (lStatus == STATUS_SUCCESS)
  320. {
  321. pEndpoint->GenHead.ulSignature = ulEndpointObject;
  322. ULONG ulTdiHandle = TSInsertNode(&pEndpoint->GenHead);
  323. if (ulTdiHandle)
  324. {
  325. lStatus = TSPerformOpenEndpoint(pEndpoint, pucString);
  326. if (lStatus == STATUS_SUCCESS)
  327. {
  328. PADDRESS_OBJECT pAddressObject;
  329. lStatus = TSAllocateMemory((PVOID *)&pAddressObject,
  330. sizeof(ADDRESS_OBJECT),
  331. strFunc5,
  332. "AddressObject");
  333. if (lStatus == STATUS_SUCCESS)
  334. {
  335. pAddressObject->GenHead.ulSignature = ulAddressObject;
  336. lStatus = TSPerformOpenAddress(pAddressObject, pucString, pTransportAddress, TRUE);
  337. if (lStatus == STATUS_SUCCESS)
  338. {
  339. pEndpoint->pAddressObject = pAddressObject;
  340. pAddressObject->pEndpoint = pEndpoint;
  341. lStatus = TSPerformAssociate(pEndpoint);
  342. if (lStatus == STATUS_SUCCESS)
  343. {
  344. pReceiveBuffer->RESULTS.TdiHandle = ulTdiHandle;
  345. return STATUS_SUCCESS;
  346. }
  347. }
  348. }
  349. //
  350. // fall thru to here on open/associate failures
  351. //
  352. }
  353. else
  354. {
  355. TSRemoveNode(ulTdiHandle);
  356. }
  357. }
  358. else
  359. {
  360. lStatus = STATUS_INSUFFICIENT_RESOURCES;
  361. }
  362. TSCloseEndpoint(pEndpoint); // also frees it!
  363. }
  364. return lStatus;
  365. }
  366. // -----------------------------------------------------------------
  367. //
  368. // Function: TSCloseEndpoint
  369. //
  370. // Arguments: pEndpoint -- endpoint object to close
  371. //
  372. // Returns: none
  373. //
  374. // Descript: This function frees the resources for a connection object,
  375. // and calls the tdi provider to close it
  376. //
  377. // ----------------------------------------------------------------------------
  378. VOID
  379. TSCloseEndpoint(PENDPOINT_OBJECT pEndpoint)
  380. {
  381. //
  382. // show debug, if it is turned on
  383. //
  384. if (ulDebugLevel & ulDebugShowCommand)
  385. {
  386. DebugPrint1("\nCommand = ulCLOSEENDPOINT\n"
  387. "Endpoint = %p\n",
  388. pEndpoint);
  389. }
  390. if (pEndpoint->pAddressObject)
  391. {
  392. if (pEndpoint->fIsAssociated)
  393. {
  394. TSPerformDisassociate(pEndpoint);
  395. }
  396. TSCloseAddress(pEndpoint->pAddressObject);
  397. pEndpoint->pAddressObject = NULL;
  398. }
  399. if (pEndpoint->GenHead.pFileObject)
  400. {
  401. ObDereferenceObject(pEndpoint->GenHead.pFileObject);
  402. NTSTATUS lStatus = ZwClose(pEndpoint->GenHead.FileHandle);
  403. if (lStatus != STATUS_SUCCESS)
  404. {
  405. DebugPrint2("%s: ZwClose failed with status 0x%08x\n",
  406. strFunc6,
  407. lStatus);
  408. }
  409. }
  410. TSFreeMemory(pEndpoint);
  411. }
  412. ////////////////////////////////////////////////////////////////
  413. // Private Functions
  414. ///////////////////////////////////////////////////////////////
  415. // ------------------------------------------------------
  416. //
  417. // Function: TSCompleteCommand
  418. //
  419. // Arguments: ptr to address object or endpoint to close for command
  420. // lstatus = status of close attempt (as TDI_STATUS)
  421. // param = 0
  422. //
  423. // Returns: none
  424. //
  425. // Descript: This function is called to complete a CloseAddress or
  426. // a CloseEndpoint on Win98
  427. //
  428. // -------------------------------------------------------
  429. #pragma warning(disable: UNREFERENCED_PARAM)
  430. TDI_STATUS
  431. TSCompleteCommand(PDEVICE_OBJECT pDeviceObject,
  432. PIRP pLowerIrp,
  433. PVOID pvContext)
  434. {
  435. TDI_STATUS TdiStatus = pLowerIrp->IoStatus.Status;
  436. PGENERIC_HEADER pGenHead = (PGENERIC_HEADER)pvContext;
  437. TSSetEvent(&pGenHead->TdiEvent);
  438. pGenHead->lStatus = TdiStatus;
  439. TSFreeIrp(pLowerIrp, NULL);
  440. return TDI_MORE_PROCESSING;
  441. }
  442. #pragma warning(default: UNREFERENCED_PARAM)
  443. // -----------------------------------------------
  444. //
  445. // Function: TSPerformOpenControl
  446. //
  447. // Arguments: pControlChannel -- used to store file information
  448. // pucString -- name of device to open
  449. //
  450. // Returns: status of operation
  451. //
  452. // Descript: Actually opens the control channel, and then sets the
  453. // appropriate fields in our structure
  454. //
  455. // -----------------------------------------------
  456. NTSTATUS
  457. TSPerformOpenControl(PCONTROL_CHANNEL pControlChannel,
  458. PUCNTSTRING pucString)
  459. {
  460. UNICODE_STRING ustrDeviceName;
  461. //
  462. // we need a unicode string to actually do the open
  463. //
  464. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
  465. pucString->usLength + 2,
  466. strFuncP2,
  467. "StringBuffer");
  468. if (lStatus == STATUS_SUCCESS)
  469. {
  470. HANDLE FileHandle;
  471. IO_STATUS_BLOCK IoStatusBlock;
  472. OBJECT_ATTRIBUTES ObjectAttributes;
  473. //
  474. // create the unicode string
  475. //
  476. ustrDeviceName.Length = pucString->usLength;
  477. ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
  478. RtlCopyMemory(ustrDeviceName.Buffer,
  479. pucString->wcBuffer,
  480. ustrDeviceName.Length);
  481. //
  482. // set up the object attributes needed to open this...
  483. //
  484. InitializeObjectAttributes(&ObjectAttributes,
  485. &ustrDeviceName,
  486. OBJ_CASE_INSENSITIVE,
  487. NULL,
  488. NULL);
  489. lStatus = ZwCreateFile(&FileHandle,
  490. GENERIC_READ | GENERIC_WRITE, // desired access.
  491. &ObjectAttributes, // object attributes.
  492. &IoStatusBlock, // returned status information.
  493. NULL, // Allocation size (unused).
  494. FILE_ATTRIBUTE_NORMAL, // file attributes.
  495. FILE_SHARE_WRITE,
  496. FILE_CREATE,
  497. 0, // create options.
  498. NULL,
  499. 0);
  500. //
  501. // make sure it really succeeded
  502. //
  503. if (NT_SUCCESS(lStatus))
  504. {
  505. lStatus = IoStatusBlock.Status;
  506. }
  507. //
  508. // clean up this now (don't need it anymore)
  509. //
  510. TSFreeMemory(ustrDeviceName.Buffer);
  511. //
  512. // if it succeeded, then set up our node structure
  513. //
  514. if (NT_SUCCESS(lStatus))
  515. {
  516. PFILE_OBJECT pFileObject;
  517. lStatus = ObReferenceObjectByHandle(FileHandle,
  518. 0,
  519. NULL,
  520. KernelMode,
  521. (PVOID *)&pFileObject,
  522. NULL);
  523. if (NT_SUCCESS(lStatus))
  524. {
  525. pControlChannel->GenHead.FileHandle = FileHandle;
  526. pControlChannel->GenHead.pFileObject = pFileObject;
  527. pControlChannel->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
  528. return STATUS_SUCCESS; // only successful exit point
  529. }
  530. else
  531. {
  532. DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
  533. lStatus);
  534. }
  535. }
  536. //
  537. // get here if ZwCreateFile failed
  538. //
  539. else
  540. {
  541. DebugPrint3("OpenControlChannel failed for %ws with code %x iostatus %x\n",
  542. pucString->wcBuffer,
  543. lStatus,
  544. IoStatusBlock.Status);
  545. }
  546. }
  547. return lStatus;
  548. }
  549. // -----------------------------------------------
  550. //
  551. // Function: TSPerformOpenAddress
  552. //
  553. // Arguments: pAddressObject -- used to store file information
  554. // pucString -- name of device to open
  555. // pTransportAddr -- address to open on the device
  556. // fIsConnect -- TRUE for connection, false for datagram
  557. //
  558. // Returns: status of operation
  559. //
  560. // Descript: Actually opens the address object, and then sets the
  561. // appropriate fields in our structure
  562. //
  563. // -----------------------------------------------
  564. NTSTATUS
  565. TSPerformOpenAddress(PADDRESS_OBJECT pAddressObject,
  566. PUCNTSTRING pucString,
  567. PTRANSPORT_ADDRESS pTransportAddress,
  568. BOOLEAN fIsConnect)
  569. {
  570. //
  571. // address open uses an ea buffer that contains the transport address
  572. //
  573. ULONG ulAddressLength
  574. = FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
  575. + FIELD_OFFSET(TA_ADDRESS, Address)
  576. + pTransportAddress->Address[0].AddressLength;
  577. ULONG ulEaLengthNeeded
  578. = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0])
  579. + (TDI_TRANSPORT_ADDRESS_LENGTH + 1)
  580. + ulAddressLength;
  581. //
  582. // allocate the ea buffer first...
  583. //
  584. PFILE_FULL_EA_INFORMATION EaBuffer;
  585. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer,
  586. ulEaLengthNeeded,
  587. strFuncP3,
  588. "EaBuffer");
  589. if (lStatus == STATUS_SUCCESS)
  590. {
  591. UNICODE_STRING ustrDeviceName;
  592. //
  593. // setup the ea buffer
  594. //
  595. EaBuffer->NextEntryOffset = 0;
  596. EaBuffer->Flags = 0;
  597. EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  598. EaBuffer->EaValueLength = (USHORT)ulAddressLength;
  599. RtlCopyMemory(&EaBuffer->EaName[0],
  600. TdiTransportAddress,
  601. TDI_TRANSPORT_ADDRESS_LENGTH + 1);
  602. RtlCopyMemory(&EaBuffer->EaName[TDI_TRANSPORT_ADDRESS_LENGTH+1],
  603. pTransportAddress,
  604. ulAddressLength);
  605. //
  606. // we need a unicode string to actually do the open
  607. //
  608. lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
  609. pucString->usLength + 2,
  610. strFuncP3,
  611. "StringBuffer");
  612. if (lStatus == STATUS_SUCCESS)
  613. {
  614. IO_STATUS_BLOCK IoStatusBlock;
  615. OBJECT_ATTRIBUTES ObjectAttributes;
  616. HANDLE FileHandle;
  617. //
  618. // create the unicode string
  619. //
  620. ustrDeviceName.Length = pucString->usLength;
  621. ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
  622. RtlCopyMemory(ustrDeviceName.Buffer,
  623. pucString->wcBuffer,
  624. ustrDeviceName.Length);
  625. //
  626. // set up the object attributes needed to open this...
  627. //
  628. InitializeObjectAttributes(&ObjectAttributes,
  629. &ustrDeviceName,
  630. OBJ_CASE_INSENSITIVE,
  631. NULL,
  632. NULL);
  633. lStatus = ZwCreateFile(&FileHandle,
  634. GENERIC_READ | GENERIC_WRITE, // desired access.
  635. &ObjectAttributes, // object attributes.
  636. &IoStatusBlock, // returned status information.
  637. NULL, // Allocation size (unused).
  638. FILE_ATTRIBUTE_NORMAL, // file attributes.
  639. FILE_SHARE_WRITE,
  640. FILE_CREATE,
  641. 0, // create options.
  642. EaBuffer,
  643. ulEaLengthNeeded);
  644. //
  645. // make sure it really succeeded
  646. //
  647. if (NT_SUCCESS(lStatus))
  648. {
  649. lStatus = IoStatusBlock.Status;
  650. }
  651. //
  652. // clean up what we can here...
  653. //
  654. TSFreeMemory(ustrDeviceName.Buffer);
  655. TSFreeMemory(EaBuffer);
  656. //
  657. // if it succeeded, then set up our node structure
  658. //
  659. if (NT_SUCCESS(lStatus))
  660. {
  661. PFILE_OBJECT pFileObject;
  662. lStatus = ObReferenceObjectByHandle(FileHandle,
  663. 0,
  664. NULL,
  665. KernelMode,
  666. (PVOID *)&pFileObject,
  667. NULL);
  668. if (NT_SUCCESS(lStatus))
  669. {
  670. pAddressObject->GenHead.FileHandle = FileHandle;
  671. pAddressObject->GenHead.pFileObject = pFileObject;
  672. pAddressObject->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
  673. TSAllocateSpinLock(&pAddressObject->TdiSpinLock);
  674. //
  675. // if ipv4, set up socket for strong host
  676. //
  677. if (fIsConnect && (pTransportAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP))
  678. {
  679. TCP_REQUEST_SET_INFORMATION_EX* pInfo;
  680. CHAR achBuf[ sizeof(*pInfo) + sizeof(ULONG) ];
  681. ULONG ulValue = 1;
  682. IO_STATUS_BLOCK iosb;
  683. pInfo = (TCP_REQUEST_SET_INFORMATION_EX* )achBuf;
  684. pInfo->ID.toi_entity.tei_entity = CL_TL_ENTITY;
  685. pInfo->ID.toi_entity.tei_instance = 0;
  686. pInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
  687. pInfo->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
  688. pInfo->ID.toi_id = AO_OPTION_IP_UCASTIF;
  689. RtlCopyMemory(pInfo->Buffer, &ulValue, sizeof(ULONG));
  690. pInfo->BufferSize = sizeof(ULONG);
  691. PIRP pIrp = IoBuildDeviceIoControlRequest(IOCTL_TCP_WSH_SET_INFORMATION_EX,
  692. pAddressObject->GenHead.pDeviceObject,
  693. (PVOID )pInfo,
  694. sizeof(*pInfo) + sizeof(ULONG),
  695. NULL,
  696. 0,
  697. FALSE,
  698. NULL,
  699. &iosb);
  700. if (pIrp)
  701. {
  702. PIO_STACK_LOCATION pIrpSp = IoGetNextIrpStackLocation(pIrp);
  703. pIrpSp->FileObject = pFileObject;
  704. IoCallDriver(pAddressObject->GenHead.pDeviceObject, pIrp);
  705. }
  706. }
  707. return STATUS_SUCCESS; // only successful exit
  708. }
  709. else
  710. {
  711. DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
  712. lStatus);
  713. }
  714. ZwClose(FileHandle);
  715. }
  716. //
  717. // get here if ZwCreateFile failed
  718. //
  719. else
  720. {
  721. DebugPrint3("OpenAddressObject failed for %ws with code %x iostatus %x\n",
  722. pucString->wcBuffer,
  723. lStatus,
  724. IoStatusBlock.Status);
  725. }
  726. }
  727. //
  728. // get here if cannot allocate unicode string buffer
  729. //
  730. else
  731. {
  732. TSFreeMemory(EaBuffer);
  733. }
  734. }
  735. return lStatus;
  736. }
  737. // -----------------------------------------------
  738. //
  739. // Function: TSPerformOpenEndpoint
  740. //
  741. // Arguments: pEndpoint -- used to store file information
  742. // pucString -- name of device to open
  743. //
  744. // Returns: status of operation
  745. //
  746. // Descript: Actually opens the endpoint object, and then sets the
  747. // appropriate fields in our structure
  748. //
  749. // -----------------------------------------------
  750. NTSTATUS
  751. TSPerformOpenEndpoint(PENDPOINT_OBJECT pEndpoint,
  752. PUCNTSTRING pucString)
  753. {
  754. //
  755. // NOTE: CONNECTION_CONTEXT == PVOID
  756. //
  757. ULONG ulEaLengthNeeded
  758. = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0])
  759. + (TDI_CONNECTION_CONTEXT_LENGTH + 1)
  760. + sizeof(CONNECTION_CONTEXT);
  761. //
  762. // allocate the ea buffer...
  763. //
  764. PFILE_FULL_EA_INFORMATION EaBuffer;
  765. NTSTATUS lStatus = TSAllocateMemory((PVOID *)&EaBuffer,
  766. ulEaLengthNeeded,
  767. strFunc5,
  768. "EaBuffer");
  769. if (lStatus == STATUS_SUCCESS)
  770. {
  771. UNICODE_STRING ustrDeviceName;
  772. //
  773. // setup the ea buffer
  774. //
  775. EaBuffer->NextEntryOffset = 0;
  776. EaBuffer->Flags = 0;
  777. EaBuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
  778. EaBuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
  779. RtlCopyMemory(&EaBuffer->EaName[0],
  780. TdiConnectionContext,
  781. TDI_CONNECTION_CONTEXT_LENGTH + 1);
  782. RtlCopyMemory(&EaBuffer->EaName[TDI_CONNECTION_CONTEXT_LENGTH+1],
  783. &pEndpoint,
  784. sizeof(CONNECTION_CONTEXT));
  785. //
  786. // we need a unicode string to actually do the open
  787. //
  788. lStatus = TSAllocateMemory((PVOID *)&ustrDeviceName.Buffer,
  789. pucString->usLength + 2,
  790. strFunc5,
  791. "StringBuffer");
  792. if (lStatus == STATUS_SUCCESS)
  793. {
  794. IO_STATUS_BLOCK IoStatusBlock;
  795. OBJECT_ATTRIBUTES ObjectAttributes;
  796. HANDLE FileHandle;
  797. //
  798. // create the unicode string
  799. //
  800. ustrDeviceName.Length = pucString->usLength;
  801. ustrDeviceName.MaximumLength = (USHORT)(pucString->usLength + 2);
  802. RtlCopyMemory(ustrDeviceName.Buffer,
  803. pucString->wcBuffer,
  804. ustrDeviceName.Length);
  805. //
  806. // set up the object attributes needed to open this...
  807. //
  808. InitializeObjectAttributes(&ObjectAttributes,
  809. &ustrDeviceName,
  810. OBJ_CASE_INSENSITIVE,
  811. NULL,
  812. NULL);
  813. lStatus = ZwCreateFile(&FileHandle,
  814. GENERIC_READ | GENERIC_WRITE, // desired access.
  815. &ObjectAttributes, // object attributes.
  816. &IoStatusBlock, // returned status information.
  817. NULL, // Allocation size (unused).
  818. FILE_ATTRIBUTE_NORMAL, // file attributes.
  819. FILE_SHARE_WRITE,
  820. FILE_CREATE,
  821. 0, // create options.
  822. EaBuffer,
  823. ulEaLengthNeeded);
  824. //
  825. // make sure it really succeeded
  826. //
  827. if (NT_SUCCESS(lStatus))
  828. {
  829. lStatus = IoStatusBlock.Status;
  830. }
  831. //
  832. // free up what we can here...
  833. //
  834. TSFreeMemory(ustrDeviceName.Buffer);
  835. TSFreeMemory(EaBuffer);
  836. //
  837. // if it succeeded, then set up our node structure
  838. //
  839. if (NT_SUCCESS(lStatus))
  840. {
  841. PFILE_OBJECT pFileObject;
  842. lStatus = ObReferenceObjectByHandle(FileHandle,
  843. 0,
  844. NULL,
  845. KernelMode,
  846. (PVOID *)&pFileObject,
  847. NULL);
  848. if (NT_SUCCESS(lStatus))
  849. {
  850. pEndpoint->GenHead.FileHandle = FileHandle;
  851. pEndpoint->GenHead.pFileObject = pFileObject;
  852. pEndpoint->GenHead.pDeviceObject = IoGetRelatedDeviceObject(pFileObject);
  853. return STATUS_SUCCESS; // only successful exit
  854. }
  855. else
  856. {
  857. DebugPrint1("ObReferenceObjectByHandle failed with status = 0x%08x\n",
  858. lStatus);
  859. }
  860. ZwClose(FileHandle);
  861. }
  862. //
  863. // get here if ZwCreateFile failed
  864. //
  865. else
  866. {
  867. DebugPrint3("OpenEndpointObject failed for %ws with code %x iostatus %x\n",
  868. pucString->wcBuffer,
  869. lStatus,
  870. IoStatusBlock.Status);
  871. }
  872. }
  873. //
  874. // get here if cannot allocate unicode string buffer
  875. //
  876. else
  877. {
  878. TSFreeMemory(EaBuffer);
  879. }
  880. }
  881. return lStatus;
  882. }
  883. // -----------------------------------------------------------------
  884. //
  885. // Function: TSPerformAssociate
  886. //
  887. // Arguments: pEndpoint -- connection endpoint structure
  888. //
  889. // Returns: NTSTATUS (normally success)
  890. //
  891. // Descript: This function attempts to associate a transport address
  892. // object with an endpoint object
  893. //
  894. // -----------------------------------------------------------------------------
  895. NTSTATUS
  896. TSPerformAssociate(PENDPOINT_OBJECT pEndpoint)
  897. {
  898. TSInitializeEvent(&pEndpoint->GenHead.TdiEvent);
  899. PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
  900. NULL);
  901. if (!pLowerIrp)
  902. {
  903. return STATUS_INSUFFICIENT_RESOURCES;
  904. }
  905. //
  906. // set up everything and call the tdi provider
  907. //
  908. #pragma warning(disable: CONSTANT_CONDITIONAL)
  909. TdiBuildAssociateAddress(pLowerIrp,
  910. pEndpoint->GenHead.pDeviceObject,
  911. pEndpoint->GenHead.pFileObject,
  912. TSCompleteCommand,
  913. pEndpoint,
  914. pEndpoint->pAddressObject->GenHead.FileHandle);
  915. #pragma warning(default: CONSTANT_CONDITIONAL)
  916. //
  917. // (should ALWAYS be pending)
  918. //
  919. NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
  920. pLowerIrp);
  921. if (lStatus == STATUS_PENDING)
  922. {
  923. TSWaitEvent(&pEndpoint->GenHead.TdiEvent);
  924. lStatus = pEndpoint->GenHead.lStatus;
  925. }
  926. if (lStatus == STATUS_SUCCESS)
  927. {
  928. pEndpoint->fIsAssociated = TRUE;
  929. }
  930. return lStatus;
  931. }
  932. // -----------------------------------------------------------------
  933. //
  934. // Function: TSPerformDisassociateAddress
  935. //
  936. // Arguments: pEndpoint -- connection endpoint structure
  937. //
  938. // Returns: NTSTATUS (normally pending)
  939. //
  940. // Descript: This function attempts to disassociate a transport address
  941. // object from its associated endpoint object
  942. //
  943. // ----------------------------------------------------------------------------
  944. VOID
  945. TSPerformDisassociate(PENDPOINT_OBJECT pEndpoint)
  946. {
  947. TSInitializeEvent(&pEndpoint->GenHead.TdiEvent);
  948. PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
  949. NULL);
  950. if (!pLowerIrp)
  951. {
  952. return;
  953. }
  954. //
  955. // set up everything and call the tdi provider
  956. //
  957. #pragma warning(disable: CONSTANT_CONDITIONAL)
  958. TdiBuildDisassociateAddress(pLowerIrp,
  959. pEndpoint->GenHead.pDeviceObject,
  960. pEndpoint->GenHead.pFileObject,
  961. TSCompleteCommand,
  962. pEndpoint);
  963. #pragma warning(default: CONSTANT_CONDITIONAL)
  964. NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
  965. pLowerIrp);
  966. if (lStatus == STATUS_PENDING)
  967. {
  968. TSWaitEvent(&pEndpoint->GenHead.TdiEvent);
  969. }
  970. }
  971. ////////////////////////////////////////////////////////////////////////////////
  972. // end of file open.cpp
  973. ////////////////////////////////////////////////////////////////////////////////