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.

1955 lines
48 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. address.c
  5. Abstract:
  6. This module contains code which implements the ADDRESS object.
  7. Routines are provided to create, destroy, reference, and dereference,
  8. transport address objects.
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. Sanjay Anand (SanjayAn) - 22-Sept-1995
  13. BackFill optimization changes added under #if BACK_FILL
  14. Sanjay Anand (SanjayAn) 3-Oct-1995
  15. Changes to support transfer of buffer ownership to transports - tagged [CH]
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. //
  20. // Map all generic accesses to the same one.
  21. //
  22. static GENERIC_MAPPING AddressGenericMapping =
  23. { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  24. TDI_ADDRESS_IPX UNALIGNED *
  25. IpxParseTdiAddress(
  26. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress
  27. )
  28. /*++
  29. Routine Description:
  30. This routine scans a TRANSPORT_ADDRESS, looking for an address
  31. of type TDI_ADDRESS_TYPE_IPX.
  32. Arguments:
  33. Transport - The generic TDI address.
  34. Return Value:
  35. A pointer to the IPX address, or NULL if none is found.
  36. --*/
  37. {
  38. TA_ADDRESS * addressName;
  39. INT i;
  40. addressName = &TransportAddress->Address[0];
  41. //
  42. // The name can be passed with multiple entries; we'll take and use only
  43. // the IPX one.
  44. //
  45. for (i=0;i<TransportAddress->TAAddressCount;i++) {
  46. if (addressName->AddressType == TDI_ADDRESS_TYPE_IPX) {
  47. if (addressName->AddressLength >= sizeof(TDI_ADDRESS_IPX)) {
  48. return ((TDI_ADDRESS_IPX UNALIGNED *)(addressName->Address));
  49. }
  50. }
  51. addressName = (TA_ADDRESS *)(addressName->Address +
  52. addressName->AddressLength);
  53. }
  54. return NULL;
  55. } /* IpxParseTdiAddress */
  56. BOOLEAN
  57. IpxValidateTdiAddress(
  58. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
  59. IN ULONG TransportAddressLength
  60. )
  61. /*++
  62. Routine Description:
  63. This routine scans a TRANSPORT_ADDRESS, verifying that the
  64. components of the address do not extend past the specified
  65. length.
  66. Arguments:
  67. TransportAddress - The generic TDI address.
  68. TransportAddressLength - The specific length of TransportAddress.
  69. Return Value:
  70. TRUE if the address is valid, FALSE otherwise.
  71. --*/
  72. {
  73. PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
  74. TA_ADDRESS * addressName;
  75. INT i;
  76. if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount)) {
  77. IpxPrint0 ("IpxValidateTdiAddress: runt address\n");
  78. return FALSE;
  79. }
  80. addressName = &TransportAddress->Address[0];
  81. for (i=0;i<TransportAddress->TAAddressCount;i++) {
  82. if (addressName->Address > AddressEnd) {
  83. IpxPrint0 ("IpxValidateTdiAddress: address too short\n");
  84. return FALSE;
  85. }
  86. addressName = (TA_ADDRESS *)(addressName->Address +
  87. addressName->AddressLength);
  88. }
  89. if ((PUCHAR)addressName > AddressEnd) {
  90. IpxPrint0 ("IpxValidateTdiAddress: address too short\n");
  91. return FALSE;
  92. }
  93. return TRUE;
  94. } /* IpxValidateTdiAddress */
  95. #if DBG
  96. VOID
  97. IpxBuildTdiAddress(
  98. IN PVOID AddressBuffer,
  99. IN ULONG Network,
  100. IN UCHAR Node[6],
  101. IN USHORT Socket
  102. )
  103. /*++
  104. Routine Description:
  105. This routine fills in a TRANSPORT_ADDRESS in the specified
  106. buffer, given the socket, network and node.
  107. Arguments:
  108. AddressBuffer - The buffer that will hold the address.
  109. Network - The network number.
  110. Node - The node address.
  111. Socket - The socket.
  112. Return Value:
  113. None.
  114. --*/
  115. {
  116. TA_IPX_ADDRESS UNALIGNED * IpxAddress;
  117. IpxAddress = (TA_IPX_ADDRESS UNALIGNED *)AddressBuffer;
  118. IpxAddress->TAAddressCount = 1;
  119. IpxAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IPX);
  120. IpxAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IPX;
  121. IpxAddress->Address[0].Address[0].NetworkAddress = Network;
  122. IpxAddress->Address[0].Address[0].Socket = Socket;
  123. RtlCopyMemory(IpxAddress->Address[0].Address[0].NodeAddress, Node, 6);
  124. } /* IpxBuildTdiAddress */
  125. #endif
  126. NTSTATUS
  127. IpxOpenAddress(
  128. IN PDEVICE Device,
  129. IN PREQUEST Request
  130. )
  131. {
  132. return(IpxOpenAddressM(Device, Request, 0));
  133. }
  134. NTSTATUS
  135. IpxOpenAddressM(
  136. IN PDEVICE Device,
  137. IN PREQUEST Request,
  138. IN ULONG Index
  139. )
  140. /*++
  141. Routine Description:
  142. This routine opens a file that points to an existing address object, or, if
  143. the object doesn't exist, creates it (note that creation of the address
  144. object includes registering the address, and may take many seconds to
  145. complete, depending upon system configuration).
  146. If the address already exists, and it has an ACL associated with it, the
  147. ACL is checked for access rights before allowing creation of the address.
  148. Arguments:
  149. Device - pointer to the device describing the IPX transport.
  150. Request - a pointer to the request used for the creation of the address.
  151. Return Value:
  152. NTSTATUS - status of operation.
  153. --*/
  154. {
  155. NTSTATUS status;
  156. PADDRESS Address;
  157. PADDRESS_FILE AddressFile;
  158. PFILE_FULL_EA_INFORMATION ea;
  159. TRANSPORT_ADDRESS UNALIGNED *name;
  160. TA_ADDRESS *AddressName;
  161. USHORT Socket;
  162. ULONG DesiredShareAccess;
  163. CTELockHandle LockHandle;
  164. PACCESS_STATE AccessState;
  165. ACCESS_MASK GrantedAccess;
  166. BOOLEAN AccessAllowed;
  167. int i;
  168. BOOLEAN found = FALSE;
  169. #ifdef ISN_NT
  170. PIRP Irp = (PIRP)Request;
  171. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  172. #endif
  173. INT Size = 0;
  174. //
  175. // If we are a dedicated router, we cannot let addresses
  176. // be opened.
  177. //
  178. if (Device->DedicatedRouter && (REQUEST_CODE(Request) != MIPX_RT_CREATE)) {
  179. return STATUS_NOT_SUPPORTED;
  180. }
  181. //
  182. // The network name is in the EA, passed in the request.
  183. //
  184. ea = OPEN_REQUEST_EA_INFORMATION(Request);
  185. if (ea == NULL) {
  186. IpxPrint1("OpenAddress: REQUEST %lx has no EA\n", Request);
  187. return STATUS_NONEXISTENT_EA_ENTRY;
  188. }
  189. //
  190. // this may be a valid name; parse the name from the EA and use it if OK.
  191. //
  192. name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
  193. //
  194. // 126042
  195. //
  196. if (ea->EaValueLength < (sizeof(TRANSPORT_ADDRESS) -1)) {
  197. IPX_DEBUG(ADDRESS, ("The ea value length does not match the TA address length\n"));
  198. DbgPrint("IPX: STATUS_INVALID_EA_NAME - 1\n");
  199. return STATUS_INVALID_EA_NAME;
  200. }
  201. AddressName = (PTA_ADDRESS)&name->Address[0];
  202. Size = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) + FIELD_OFFSET(TA_ADDRESS, Address) + AddressName->AddressLength;
  203. //
  204. // The name can be passed with multiple entries; we'll take and use only
  205. // the first one of type IPX.
  206. //
  207. //DbgPrint("Size (%d) & EaValueLength (%d)", Size, ea->EaValueLength);
  208. if (Size > ea->EaValueLength) {
  209. DbgPrint("EA:%lx, Name:%lx, AddressName:%lx\n", ea, name, AddressName);
  210. CTEAssert(FALSE);
  211. }
  212. for (i=0;i<name->TAAddressCount;i++) {
  213. //
  214. // 126042
  215. //
  216. if (Size > ea->EaValueLength) {
  217. IPX_DEBUG(ADDRESS, ("The EA value length does not match the TA address length (2)\n"));
  218. DbgPrint("IPX: STATUS_INVALID_EA_NAME - 2\n");
  219. return STATUS_INVALID_EA_NAME;
  220. }
  221. if (AddressName->AddressType == TDI_ADDRESS_TYPE_IPX) {
  222. if (AddressName->AddressLength >= sizeof(TDI_ADDRESS_IPX)) {
  223. Socket = ((TDI_ADDRESS_IPX UNALIGNED *)&AddressName->Address[0])->Socket;
  224. found = TRUE;
  225. }
  226. break;
  227. } else {
  228. AddressName = (PTA_ADDRESS)(AddressName->Address +
  229. AddressName->AddressLength);
  230. Size += FIELD_OFFSET(TA_ADDRESS, Address);
  231. if (Size < ea->EaValueLength) {
  232. Size += AddressName->AddressLength;
  233. } else {
  234. break;
  235. }
  236. }
  237. }
  238. if (!found) {
  239. IPX_DEBUG (ADDRESS, ("OpenAddress, request %lx has no IPX Address\n", Request));
  240. return STATUS_NONEXISTENT_EA_ENTRY;
  241. }
  242. if (Socket == 0) {
  243. Socket = IpxAssignSocket (Device);
  244. if (Socket == 0) {
  245. IPX_DEBUG (ADDRESS, ("OpenAddress, no unique socket found\n"));
  246. #ifdef SNMP
  247. ++IPX_MIB_ENTRY(Device, SysOpenSocketFails);
  248. #endif SNMP
  249. return STATUS_INSUFFICIENT_RESOURCES;
  250. } else {
  251. IPX_DEBUG (ADDRESS, ("OpenAddress, assigned socket %lx\n", REORDER_USHORT(Socket)));
  252. }
  253. } else {
  254. IPX_DEBUG (ADDRESS, ("OpenAddress, socket %lx\n", REORDER_USHORT(Socket)));
  255. }
  256. //
  257. // get an address file structure to represent this address.
  258. //
  259. AddressFile = IpxCreateAddressFile (Device);
  260. if (AddressFile == (PADDRESS_FILE)NULL) {
  261. return STATUS_INSUFFICIENT_RESOURCES;
  262. }
  263. //
  264. // We mark this socket specially.
  265. //
  266. if (Socket == SAP_SOCKET) {
  267. AddressFile->IsSapSocket = TRUE;
  268. AddressFile->SpecialReceiveProcessing = TRUE;
  269. }
  270. //
  271. // See if this address is already established. This call automatically
  272. // increments the reference count on the address so that it won't disappear
  273. // from underneath us after this call but before we have a chance to use it.
  274. //
  275. // To ensure that we don't create two address objects for the
  276. // same address, we hold the device context addressResource until
  277. // we have found the address or created a new one.
  278. //
  279. KeEnterCriticalRegion();
  280. ExAcquireResourceExclusiveLite (&Device->AddressResource, TRUE);
  281. CTEGetLock (&Device->Lock, &LockHandle);
  282. Address = IpxLookupAddress (Device, Socket);
  283. if (Address == NULL) {
  284. CTEFreeLock (&Device->Lock, LockHandle);
  285. //
  286. // This address doesn't exist. Create it.
  287. // registering it.
  288. //
  289. Address = IpxCreateAddress (
  290. Device,
  291. Socket);
  292. if (Address != (PADDRESS)NULL) {
  293. //
  294. // Set this now in case we have to deref.
  295. //
  296. AddressFile->AddressLock = &Address->Lock;
  297. if (REQUEST_CODE(Request) == MIPX_RT_CREATE) {
  298. Address->RtAdd = TRUE;
  299. Address->Index = Index;
  300. } else {
  301. Address->RtAdd = FALSE;
  302. }
  303. #ifdef ISN_NT
  304. //
  305. // Initialize the shared access now. We use read access
  306. // to control all access.
  307. //
  308. DesiredShareAccess = (ULONG)
  309. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  310. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  311. FILE_SHARE_READ : 0);
  312. IoSetShareAccess(
  313. FILE_READ_DATA,
  314. DesiredShareAccess,
  315. IrpSp->FileObject,
  316. &Address->u.ShareAccess);
  317. //
  318. // Assign the security descriptor (need to do this with
  319. // the spinlock released because the descriptor is not
  320. // mapped).
  321. //
  322. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  323. status = SeAssignSecurity(
  324. NULL, // parent descriptor
  325. AccessState->SecurityDescriptor,
  326. &Address->SecurityDescriptor,
  327. FALSE, // is directory
  328. &AccessState->SubjectSecurityContext,
  329. &AddressGenericMapping,
  330. NonPagedPool);
  331. if (!NT_SUCCESS(status)) {
  332. //
  333. // Error, return status.
  334. //
  335. IoRemoveShareAccess (IrpSp->FileObject, &Address->u.ShareAccess);
  336. ExReleaseResourceLite (&Device->AddressResource);
  337. KeLeaveCriticalRegion();
  338. IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
  339. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  340. return status;
  341. }
  342. #endif
  343. ExReleaseResourceLite (&Device->AddressResource);
  344. KeLeaveCriticalRegion();
  345. //
  346. // if the adapter isn't ready, we can't do any of this; get out
  347. //
  348. if (Device->State == DEVICE_STATE_STOPPING) {
  349. IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
  350. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  351. status = STATUS_DEVICE_NOT_READY;
  352. } else {
  353. REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
  354. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  355. #ifdef ISN_NT
  356. AddressFile->FileObject = IrpSp->FileObject;
  357. #endif
  358. AddressFile->Request = Request;
  359. AddressFile->Address = Address;
  360. CTEGetLock (&Address->Lock, &LockHandle);
  361. InsertTailList (&Address->AddressFileDatabase, &AddressFile->Linkage);
  362. CTEFreeLock (&Address->Lock, LockHandle);
  363. AddressFile->Request = NULL;
  364. AddressFile->State = ADDRESSFILE_STATE_OPEN;
  365. status = STATUS_SUCCESS;
  366. }
  367. } else {
  368. ExReleaseResourceLite (&Device->AddressResource);
  369. KeLeaveCriticalRegion();
  370. //
  371. // If the address could not be created, and is not in the
  372. // process of being created, then we can't open up an address.
  373. // Since we can't use the AddressLock to deref, we just destroy
  374. // the address file.
  375. //
  376. IpxDestroyAddressFile (AddressFile);
  377. // 288208
  378. status = STATUS_INSUFFICIENT_RESOURCES;
  379. }
  380. } else {
  381. CTEFreeLock (&Device->Lock, LockHandle);
  382. IPX_DEBUG (ADDRESS, ("Add to address %lx\n", Address));
  383. //
  384. // We never allow shared access to a RT address. So, check that
  385. // we don't have a "RT address create" request and also that the
  386. // address has not only been taken up by a RT Address request. If
  387. // and only if both the above
  388. //
  389. if ((REQUEST_CODE(Request) != MIPX_RT_CREATE) && (!Address->RtAdd))
  390. {
  391. //
  392. // Set this now in case we have to deref.
  393. //
  394. AddressFile->AddressLock = &Address->Lock;
  395. //
  396. // The address already exists. Check the ACL and see if we
  397. // can access it. If so, simply use this address as our address.
  398. //
  399. #ifdef ISN_NT
  400. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  401. AccessAllowed = SeAccessCheck(
  402. Address->SecurityDescriptor,
  403. &AccessState->SubjectSecurityContext,
  404. FALSE, // tokens locked
  405. IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
  406. (ACCESS_MASK)0, // previously granted
  407. NULL, // privileges
  408. &AddressGenericMapping,
  409. Irp->RequestorMode,
  410. &GrantedAccess,
  411. &status);
  412. #else // ISN_NT
  413. AccessAllowed = TRUE;
  414. #endif // ISN_NT
  415. if (!AccessAllowed) {
  416. ExReleaseResourceLite (&Device->AddressResource);
  417. KeLeaveCriticalRegion();
  418. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  419. } else {
  420. #ifdef ISN_NT
  421. //
  422. // NtBug: 132051. Make sure you dont give more access than reqd.
  423. //
  424. AccessState->PreviouslyGrantedAccess |= GrantedAccess;
  425. AccessState->RemainingDesiredAccess &= ~( GrantedAccess | MAXIMUM_ALLOWED );
  426. //
  427. // Now check that we can obtain the desired share
  428. // access. We use read access to control all access.
  429. //
  430. DesiredShareAccess = (ULONG)
  431. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  432. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  433. FILE_SHARE_READ : 0);
  434. status = IoCheckShareAccess(
  435. FILE_READ_DATA,
  436. DesiredShareAccess,
  437. IrpSp->FileObject,
  438. &Address->u.ShareAccess,
  439. TRUE);
  440. #else // ISN_NT
  441. status = STATUS_SUCCESS;
  442. #endif // ISN_NT
  443. if (!NT_SUCCESS (status)) {
  444. ExReleaseResourceLite (&Device->AddressResource);
  445. KeLeaveCriticalRegion();
  446. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  447. } else {
  448. ExReleaseResourceLite (&Device->AddressResource);
  449. KeLeaveCriticalRegion();
  450. CTEGetLock (&Address->Lock, &LockHandle);
  451. InsertTailList (
  452. &Address->AddressFileDatabase,
  453. &AddressFile->Linkage);
  454. AddressFile->Request = NULL;
  455. AddressFile->Address = Address;
  456. #ifdef ISN_NT
  457. AddressFile->FileObject = IrpSp->FileObject;
  458. #endif
  459. AddressFile->State = ADDRESSFILE_STATE_OPEN;
  460. IpxReferenceAddress (Address, AREF_ADDRESS_FILE);
  461. REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
  462. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  463. CTEFreeLock (&Address->Lock, LockHandle);
  464. status = STATUS_SUCCESS;
  465. }
  466. }
  467. }
  468. else
  469. {
  470. DbgPrint("IpxOpenAddress: ACCESS DENIED - duplicate address\n");
  471. status = STATUS_ACCESS_DENIED;
  472. ExReleaseResourceLite (&Device->AddressResource);
  473. KeLeaveCriticalRegion();
  474. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  475. }
  476. //
  477. // Remove the reference from IpxLookupAddress.
  478. //
  479. IpxDereferenceAddress (Address, AREF_LOOKUP);
  480. }
  481. return status;
  482. } /* IpxOpenAddress */
  483. USHORT
  484. IpxAssignSocket(
  485. IN PDEVICE Device
  486. )
  487. /*++
  488. Routine Description:
  489. This routine assigns a socket that is unique within a range
  490. of SocketUniqueness.
  491. Arguments:
  492. Device - Pointer to the device context.
  493. Return Value:
  494. The assigned socket number, or 0 if a unique one cannot
  495. be found.
  496. --*/
  497. {
  498. USHORT InitialSocket, CurrentSocket, AddressSocket;
  499. ULONG CurrentHash;
  500. BOOLEAN Conflict;
  501. PLIST_ENTRY p;
  502. PADDRESS Address;
  503. CTELockHandle LockHandle;
  504. //
  505. // Loop through all possible sockets, starting at
  506. // Device->CurrentSocket, looking for a suitable one.
  507. // Device->CurrentSocket rotates through the possible
  508. // sockets to improve the chances of finding one
  509. // quickly.
  510. //
  511. CTEGetLock (&Device->Lock, &LockHandle);
  512. InitialSocket = Device->CurrentSocket;
  513. Device->CurrentSocket = (USHORT)(Device->CurrentSocket + Device->SocketUniqueness);
  514. if ((USHORT)(Device->CurrentSocket+Device->SocketUniqueness) > Device->SocketEnd) {
  515. Device->CurrentSocket = Device->SocketStart;
  516. }
  517. CurrentSocket = InitialSocket;
  518. do {
  519. //
  520. // Scan all addresses; if we find one with a socket
  521. // that conflicts with this one, we can't use it.
  522. //
  523. // NOTE: Device->Lock is acquired here.
  524. //
  525. Conflict = FALSE;
  526. for (CurrentHash = 0; CurrentHash < IPX_ADDRESS_HASH_COUNT; CurrentHash++) {
  527. for (p = Device->AddressDatabases[CurrentHash].Flink;
  528. p != &Device->AddressDatabases[CurrentHash];
  529. p = p->Flink) {
  530. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  531. AddressSocket = REORDER_USHORT(Address->Socket);
  532. if ((AddressSocket + Device->SocketUniqueness > CurrentSocket) &&
  533. (AddressSocket < CurrentSocket + Device->SocketUniqueness)) {
  534. Conflict = TRUE;
  535. break;
  536. }
  537. }
  538. //
  539. // If we've found a conflict, no need to check the other
  540. // queues.
  541. //
  542. if (Conflict) {
  543. break;
  544. }
  545. }
  546. CTEFreeLock (&Device->Lock, LockHandle);
  547. //
  548. // We intentionally free the lock here so that we
  549. // never spend too much time with it held.
  550. //
  551. if (!Conflict) {
  552. //
  553. // We went through the address list without
  554. // finding a conflict; use this socket.
  555. //
  556. return REORDER_USHORT(CurrentSocket);
  557. }
  558. CurrentSocket = (USHORT)(CurrentSocket + Device->SocketUniqueness);
  559. if ((USHORT)(CurrentSocket+Device->SocketUniqueness) > Device->SocketEnd) {
  560. CurrentSocket = Device->SocketStart;
  561. }
  562. CTEGetLock (&Device->Lock, &LockHandle);
  563. } while (CurrentSocket != InitialSocket);
  564. CTEFreeLock (&Device->Lock, LockHandle);
  565. //
  566. // Could not find one to assign.
  567. //
  568. return (USHORT)0;
  569. } /* IpxAssignSocket */
  570. PADDRESS
  571. IpxCreateAddress(
  572. IN PDEVICE Device,
  573. IN USHORT Socket
  574. )
  575. /*++
  576. Routine Description:
  577. This routine creates a transport address and associates it with
  578. the specified transport device context. The reference count in the
  579. address is automatically set to 1, and the reference count of the
  580. device context is incremented.
  581. NOTE: This routine must be called with the Device
  582. spinlock held.
  583. Arguments:
  584. Device - Pointer to the device context (which is really just
  585. the device object with its extension) to be associated with the
  586. address.
  587. Socket - The socket to assign to this address.
  588. Return Value:
  589. The newly created address, or NULL if none can be allocated.
  590. --*/
  591. {
  592. PADDRESS Address;
  593. PIPX_SEND_RESERVED SendReserved;
  594. PIPX_RECEIVE_RESERVED ReceiveReserved;
  595. NDIS_STATUS Status;
  596. IPX_DEFINE_LOCK_HANDLE (LockHandle)
  597. Address = (PADDRESS)IpxAllocateMemory (sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
  598. if (Address == NULL) {
  599. IPX_DEBUG (ADDRESS, ("Create address %lx failed\n", REORDER_USHORT(Socket)));
  600. return NULL;
  601. }
  602. IPX_DEBUG (ADDRESS, ("Create address %lx (%lx)\n", Address, REORDER_USHORT(Socket)));
  603. RtlZeroMemory (Address, sizeof(ADDRESS));
  604. #ifndef IPX_OWN_PACKETS
  605. IpxAllocateSingleSendPacket(Device, &Address->SendPacket, &Status);
  606. if (Status != NDIS_STATUS_SUCCESS) {
  607. goto Fail1;
  608. }
  609. #endif
  610. if (IpxInitializeSendPacket (Device, &Address->SendPacket, Address->SendPacketHeader) != STATUS_SUCCESS) {
  611. #ifndef IPX_OWN_PACKETS
  612. Fail1:
  613. #endif
  614. Address->SendPacketInUse = TRUE;
  615. } else {
  616. SendReserved = SEND_RESERVED(&Address->SendPacket);
  617. SendReserved->Address = Address;
  618. SendReserved->OwnedByAddress = TRUE;
  619. Address->SendPacketInUse = FALSE;
  620. #ifdef IPX_TRACK_POOL
  621. SendReserved->Pool = NULL;
  622. #endif
  623. }
  624. #if BACK_FILL
  625. {
  626. PIPX_SEND_RESERVED BackFillReserved;
  627. #ifndef IPX_OWN_PACKETS
  628. IpxAllocateSingleSendPacket(Device, &Address->BackFillPacket, &Status);
  629. if (Status != NDIS_STATUS_SUCCESS) {
  630. goto Fail2;
  631. }
  632. #endif
  633. if (IpxInitializeBackFillPacket (Device, &Address->BackFillPacket, NULL) != STATUS_SUCCESS) {
  634. #ifndef IPX_OWN_PACKETS
  635. Fail2:
  636. #endif
  637. Address->BackFillPacketInUse = TRUE;
  638. } else {
  639. BackFillReserved = SEND_RESERVED(&Address->BackFillPacket);
  640. BackFillReserved->Address = Address;
  641. Address->BackFillPacketInUse = FALSE;
  642. BackFillReserved->OwnedByAddress = TRUE;
  643. #ifdef IPX_TRACK_POOL
  644. BackFillReserved->Pool = NULL;
  645. #endif
  646. }
  647. }
  648. #endif
  649. #ifndef IPX_OWN_PACKETS
  650. IpxAllocateSingleReceivePacket(Device, &Address->ReceivePacket, &Status);
  651. if (Status != NDIS_STATUS_SUCCESS) {
  652. goto Fail3;
  653. }
  654. #endif
  655. if (IpxInitializeReceivePacket (Device, &Address->ReceivePacket) != STATUS_SUCCESS) {
  656. #ifndef IPX_OWN_PACKETS
  657. Fail3:
  658. #endif
  659. Address->ReceivePacketInUse = TRUE;
  660. } else {
  661. ReceiveReserved = RECEIVE_RESERVED(&Address->ReceivePacket);
  662. ReceiveReserved->Address = Address;
  663. ReceiveReserved->OwnedByAddress = TRUE;
  664. Address->ReceivePacketInUse = FALSE;
  665. #ifdef IPX_TRACK_POOL
  666. ReceiveReserved->Pool = NULL;
  667. #endif
  668. }
  669. Address->Type = IPX_ADDRESS_SIGNATURE;
  670. Address->Size = sizeof (ADDRESS);
  671. Address->Device = Device;
  672. Address->DeviceLock = &Device->Lock;
  673. CTEInitLock (&Address->Lock);
  674. InitializeListHead (&Address->AddressFileDatabase);
  675. Address->ReferenceCount = 1;
  676. #if DBG
  677. Address->RefTypes[AREF_ADDRESS_FILE] = 1;
  678. #endif
  679. Address->Socket = Socket;
  680. Address->SendSourceSocket = Socket;
  681. //
  682. // Save our local address for building datagrams quickly.
  683. //
  684. RtlCopyMemory (&Address->LocalAddress, &Device->SourceAddress, FIELD_OFFSET(TDI_ADDRESS_IPX,Socket));
  685. Address->LocalAddress.Socket = Socket;
  686. //
  687. // Now link this address into the specified device context's
  688. // address database. To do this, we need to acquire the spin lock
  689. // on the device context.
  690. //
  691. IPX_GET_LOCK (&Device->Lock, &LockHandle);
  692. InsertTailList (&Device->AddressDatabases[IPX_HASH_SOCKET(Socket)], &Address->Linkage);
  693. IPX_FREE_LOCK (&Device->Lock, LockHandle);
  694. IpxReferenceDevice (Device, DREF_ADDRESS);
  695. return Address;
  696. } /* IpxCreateAddress */
  697. NTSTATUS
  698. IpxVerifyAddressFile(
  699. IN PADDRESS_FILE AddressFile
  700. )
  701. /*++
  702. Routine Description:
  703. This routine is called to verify that the pointer given us in a file
  704. object is in fact a valid address file object. We also verify that the
  705. address object pointed to by it is a valid address object, and reference
  706. it to keep it from disappearing while we use it.
  707. Arguments:
  708. AddressFile - potential pointer to a ADDRESS_FILE object
  709. Return Value:
  710. STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
  711. --*/
  712. {
  713. CTELockHandle LockHandle;
  714. NTSTATUS status = STATUS_SUCCESS;
  715. PADDRESS Address;
  716. //
  717. // try to verify the address file signature. If the signature is valid,
  718. // verify the address pointed to by it and get the address spinlock.
  719. // check the address's state, and increment the reference count if it's
  720. // ok to use it. Note that the only time we return an error for state is
  721. // if the address is closing.
  722. //
  723. try {
  724. if ((AddressFile->Size == sizeof (ADDRESS_FILE)) &&
  725. (AddressFile->Type == IPX_ADDRESSFILE_SIGNATURE) ) {
  726. // (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) {
  727. Address = AddressFile->Address;
  728. if ((Address->Size == sizeof (ADDRESS)) &&
  729. (Address->Type == IPX_ADDRESS_SIGNATURE) ) {
  730. CTEGetLock (&Address->Lock, &LockHandle);
  731. if (!Address->Stopping) {
  732. IpxReferenceAddressFileLock (AddressFile, AFREF_VERIFY);
  733. } else {
  734. IpxPrint1("IpxVerifyAddressFile: A %lx closing\n", Address);
  735. status = STATUS_INVALID_ADDRESS;
  736. }
  737. CTEFreeLock (&Address->Lock, LockHandle);
  738. } else {
  739. IpxPrint1("IpxVerifyAddressFile: A %lx bad signature\n", Address);
  740. status = STATUS_INVALID_ADDRESS;
  741. }
  742. } else {
  743. IpxPrint1("IpxVerifyAddressFile: AF %lx bad signature\n", AddressFile);
  744. status = STATUS_INVALID_ADDRESS;
  745. }
  746. } except(EXCEPTION_EXECUTE_HANDLER) {
  747. IpxPrint1("IpxVerifyAddressFile: AF %lx exception\n", Address);
  748. return GetExceptionCode();
  749. }
  750. return status;
  751. } /* IpxVerifyAddressFile */
  752. VOID
  753. IpxDestroyAddress(
  754. IN PVOID Parameter
  755. )
  756. /*++
  757. Routine Description:
  758. This routine destroys a transport address and removes all references
  759. made by it to other objects in the transport. The address structure
  760. is returned to nonpaged system pool. It is assumed
  761. that the caller has already removed all addressfile structures associated
  762. with this address.
  763. It is called from a worker thread queue by IpxDerefAddress when
  764. the reference count goes to 0.
  765. This thread is only queued by IpxDerefAddress. The reason for
  766. this is that there may be multiple streams of execution which are
  767. simultaneously referencing the same address object, and it should
  768. not be deleted out from under an interested stream of execution.
  769. Arguments:
  770. Address - Pointer to a transport address structure to be destroyed.
  771. Return Value:
  772. NTSTATUS - status of operation.
  773. --*/
  774. {
  775. PADDRESS Address = (PADDRESS)Parameter;
  776. PDEVICE Device = Address->Device;
  777. CTELockHandle LockHandle;
  778. IPX_DEBUG (ADDRESS, ("Destroy address %lx (%lx)\n", Address, REORDER_USHORT(Address->Socket)));
  779. SeDeassignSecurity (&Address->SecurityDescriptor);
  780. //
  781. // Delink this address from its associated device context's address
  782. // database. To do this we must spin lock on the device context object,
  783. // not on the address.
  784. //
  785. CTEGetLock (&Device->Lock, &LockHandle);
  786. RemoveEntryList (&Address->Linkage);
  787. CTEFreeLock (&Device->Lock, LockHandle);
  788. if (!Address->SendPacketInUse) {
  789. IpxDeinitializeSendPacket (Device, &Address->SendPacket);
  790. #ifndef IPX_OWN_PACKETS
  791. IpxFreeSingleSendPacket (Device, Address->SendPacket);
  792. #endif
  793. }
  794. if (!Address->ReceivePacketInUse) {
  795. IpxDeinitializeReceivePacket (Device, &Address->ReceivePacket);
  796. #ifndef IPX_OWN_PACKETS
  797. IpxFreeSingleReceivePacket (Device, Address->ReceivePacket);
  798. #endif
  799. }
  800. #if BACK_FILL
  801. if (!Address->BackFillPacketInUse) {
  802. IpxDeinitializeBackFillPacket (Device, &Address->BackFillPacket);
  803. #ifndef IPX_OWN_PACKETS
  804. IpxFreeSingleSendPacket (Device, Address->BackFillPacket);
  805. #endif
  806. }
  807. #endif
  808. IpxFreeMemory (Address, sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
  809. IpxDereferenceDevice (Device, DREF_ADDRESS);
  810. } /* IpxDestroyAddress */
  811. #if DBG
  812. VOID
  813. IpxRefAddress(
  814. IN PADDRESS Address
  815. )
  816. /*++
  817. Routine Description:
  818. This routine increments the reference count on a transport address.
  819. Arguments:
  820. Address - Pointer to a transport address object.
  821. Return Value:
  822. none.
  823. --*/
  824. {
  825. CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
  826. (VOID)InterlockedIncrement(&Address->ReferenceCount);
  827. } /* IpxRefAddress */
  828. VOID
  829. IpxRefAddressLock(
  830. IN PADDRESS Address
  831. )
  832. /*++
  833. Routine Description:
  834. This routine increments the reference count on a transport address
  835. when the device lock is already held.
  836. Arguments:
  837. Address - Pointer to a transport address object.
  838. Return Value:
  839. none.
  840. --*/
  841. {
  842. CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
  843. // ++Address->ReferenceCount;
  844. (VOID)InterlockedIncrement(&Address->ReferenceCount);
  845. } /* IpxRefAddressLock */
  846. #endif
  847. VOID
  848. IpxDerefAddress(
  849. IN PADDRESS Address
  850. )
  851. /*++
  852. Routine Description:
  853. This routine dereferences a transport address by decrementing the
  854. reference count contained in the structure. If, after being
  855. decremented, the reference count is zero, then this routine calls
  856. IpxDestroyAddress to remove it from the system.
  857. Arguments:
  858. Address - Pointer to a transport address object.
  859. Return Value:
  860. none.
  861. --*/
  862. {
  863. ULONG oldvalue;
  864. oldvalue = IPX_ADD_ULONG (
  865. &Address->ReferenceCount,
  866. (ULONG)-1,
  867. Address->DeviceLock);
  868. //
  869. // If we have deleted all references to this address, then we can
  870. // destroy the object. It is okay to have already released the spin
  871. // lock at this point because there is no possible way that another
  872. // stream of execution has access to the address any longer.
  873. //
  874. CTEAssert (oldvalue != 0);
  875. if (oldvalue == 1) {
  876. #if ISN_NT
  877. ExInitializeWorkItem(
  878. &Address->u.DestroyAddressQueueItem,
  879. IpxDestroyAddress,
  880. (PVOID)Address);
  881. ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
  882. #else
  883. IpxDestroyAddress(Address);
  884. #endif
  885. }
  886. } /* IpxDerefAddress */
  887. VOID
  888. IpxDerefAddressSync(
  889. IN PADDRESS Address
  890. )
  891. /*++
  892. Routine Description:
  893. This routine dereferences a transport address by decrementing the
  894. reference count contained in the structure. If, after being
  895. decremented, the reference count is zero, then this routine calls
  896. IpxDestroyAddress to remove it from the system. This routine can
  897. only be called when we are synchronized (inside an IPX_SYNC_START/
  898. IPX_SYNC_END pair, with a lock held, or in an indication).
  899. Arguments:
  900. Address - Pointer to a transport address object.
  901. Return Value:
  902. none.
  903. --*/
  904. {
  905. ULONG oldvalue;
  906. oldvalue = IPX_ADD_ULONG (
  907. &Address->ReferenceCount,
  908. (ULONG)-1,
  909. Address->DeviceLock);
  910. //
  911. // If we have deleted all references to this address, then we can
  912. // destroy the object. It is okay to have already released the spin
  913. // lock at this point because there is no possible way that another
  914. // stream of execution has access to the address any longer.
  915. //
  916. CTEAssert (oldvalue != 0);
  917. if (oldvalue == 1) {
  918. #if ISN_NT
  919. ExInitializeWorkItem(
  920. &Address->u.DestroyAddressQueueItem,
  921. IpxDestroyAddress,
  922. (PVOID)Address);
  923. ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
  924. #else
  925. IpxDestroyAddress(Address);
  926. #endif
  927. }
  928. } /* IpxDerefAddressSync */
  929. PADDRESS_FILE
  930. IpxCreateAddressFile(
  931. IN PDEVICE Device
  932. )
  933. /*++
  934. Routine Description:
  935. This routine creates an address file from the pool of ther
  936. specified device context. The reference count in the
  937. address is automatically set to 1.
  938. Arguments:
  939. Device - Pointer to the device context (which is really just
  940. the device object with its extension) to be associated with the
  941. address.
  942. Return Value:
  943. The allocate address file or NULL.
  944. --*/
  945. {
  946. CTELockHandle LockHandle;
  947. PADDRESS_FILE AddressFile;
  948. AddressFile = (PADDRESS_FILE)IpxAllocateMemory (sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
  949. if (AddressFile == NULL) {
  950. IPX_DEBUG (ADDRESS, ("Create address file failed\n"));
  951. return NULL;
  952. }
  953. IPX_DEBUG (ADDRESS, ("Create address file %lx\n", AddressFile));
  954. RtlZeroMemory (AddressFile, sizeof(ADDRESS_FILE));
  955. AddressFile->Type = IPX_ADDRESSFILE_SIGNATURE;
  956. AddressFile->Size = sizeof (ADDRESS_FILE);
  957. CTEGetLock (&Device->Lock, &LockHandle);
  958. InitializeListHead (&AddressFile->ReceiveDatagramQueue);
  959. CTEFreeLock (&Device->Lock, LockHandle);
  960. #if 0
  961. AddressFile->SpecialReceiveProcessing = FALSE;
  962. AddressFile->ExtendedAddressing = FALSE;
  963. AddressFile->ReceiveIpxHeader = FALSE;
  964. AddressFile->FilterOnPacketType = FALSE;
  965. AddressFile->DefaultPacketType = 0;
  966. AddressFile->Address = NULL;
  967. #ifdef ISN_NT
  968. AddressFile->FileObject = NULL;
  969. #endif
  970. #endif
  971. AddressFile->Device = Device;
  972. AddressFile->State = ADDRESSFILE_STATE_OPENING;
  973. AddressFile->ReferenceCount = 1;
  974. #if DBG
  975. AddressFile->RefTypes[AFREF_CREATE] = 1;
  976. #endif
  977. AddressFile->CloseRequest = (PREQUEST)NULL;
  978. //
  979. // Initialize the request handlers.
  980. //
  981. AddressFile->RegisteredReceiveDatagramHandler = FALSE;
  982. AddressFile->ReceiveDatagramHandler = TdiDefaultRcvDatagramHandler;
  983. AddressFile->ReceiveDatagramHandlerContext = NULL;
  984. //
  985. // [CH] Added these handlers for chained buffer receives
  986. //
  987. AddressFile->RegisteredChainedReceiveDatagramHandler = FALSE;
  988. AddressFile->ChainedReceiveDatagramHandler = TdiDefaultChainedRcvDatagramHandler;
  989. AddressFile->ChainedReceiveDatagramHandlerContext = NULL;
  990. AddressFile->RegisteredErrorHandler = FALSE;
  991. AddressFile->ErrorHandler = TdiDefaultErrorHandler;
  992. AddressFile->ErrorHandlerContext = NULL;
  993. return AddressFile;
  994. } /* IpxCreateAddressFile */
  995. NTSTATUS
  996. IpxDestroyAddressFile(
  997. IN PADDRESS_FILE AddressFile
  998. )
  999. /*++
  1000. Routine Description:
  1001. This routine destroys an address file and removes all references
  1002. made by it to other objects in the transport.
  1003. This routine is only called by IpxDereferenceAddressFile. The reason
  1004. for this is that there may be multiple streams of execution which are
  1005. simultaneously referencing the same address file object, and it should
  1006. not be deleted out from under an interested stream of execution.
  1007. Arguments:
  1008. AddressFile Pointer to a transport address file structure to be destroyed.
  1009. Return Value:
  1010. NTSTATUS - status of operation.
  1011. --*/
  1012. {
  1013. CTELockHandle LockHandle, LockHandle1;
  1014. PADDRESS Address;
  1015. PDEVICE Device;
  1016. PREQUEST CloseRequest;
  1017. IPX_DEBUG (ADDRESS, ("Destroy address file %lx\n", AddressFile));
  1018. Address = AddressFile->Address;
  1019. Device = AddressFile->Device;
  1020. if (Address) {
  1021. //
  1022. // This addressfile was associated with an address.
  1023. //
  1024. CTEGetLock (&Address->Lock, &LockHandle);
  1025. //
  1026. // remove this addressfile from the address list and disassociate it from
  1027. // the file handle.
  1028. //
  1029. RemoveEntryList (&AddressFile->Linkage);
  1030. InitializeListHead (&AddressFile->Linkage);
  1031. if (Address->AddressFileDatabase.Flink == &Address->AddressFileDatabase) {
  1032. //
  1033. // This is the last open of this address, it will close
  1034. // due to normal dereferencing but we have to set the
  1035. // CLOSING flag too to stop further references.
  1036. //
  1037. CTEGetLock (&Device->Lock, &LockHandle1);
  1038. Address->Stopping = TRUE;
  1039. if (Device->LastAddress == Address) {
  1040. Device->LastAddress = NULL;
  1041. }
  1042. CTEFreeLock (&Device->Lock, LockHandle1);
  1043. }
  1044. AddressFile->Address = NULL;
  1045. #ifdef ISN_NT
  1046. AddressFile->FileObject->FsContext = NULL;
  1047. AddressFile->FileObject->FsContext2 = NULL;
  1048. #endif
  1049. CTEFreeLock (&Address->Lock, LockHandle);
  1050. //
  1051. // We will already have been removed from the ShareAccess
  1052. // of the owning address.
  1053. //
  1054. //
  1055. // Now dereference the owning address.
  1056. //
  1057. IpxDereferenceAddress (Address, AREF_ADDRESS_FILE);
  1058. }
  1059. //
  1060. // Save this for later completion.
  1061. //
  1062. CloseRequest = AddressFile->CloseRequest;
  1063. //
  1064. // return the addressFile to the pool of address files
  1065. //
  1066. IpxFreeMemory (AddressFile, sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
  1067. if (CloseRequest != (PREQUEST)NULL) {
  1068. REQUEST_INFORMATION(CloseRequest) = 0;
  1069. REQUEST_STATUS(CloseRequest) = STATUS_SUCCESS;
  1070. IpxCompleteRequest (CloseRequest);
  1071. IpxFreeRequest (Device, CloseRequest);
  1072. }
  1073. return STATUS_SUCCESS;
  1074. } /* IpxDestroyAddressFile */
  1075. #if DBG
  1076. VOID
  1077. IpxRefAddressFile(
  1078. IN PADDRESS_FILE AddressFile
  1079. )
  1080. /*++
  1081. Routine Description:
  1082. This routine increments the reference count on an address file.
  1083. Arguments:
  1084. AddressFile - Pointer to a transport address file object.
  1085. Return Value:
  1086. none.
  1087. --*/
  1088. {
  1089. CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
  1090. (VOID)IPX_ADD_ULONG (
  1091. &AddressFile->ReferenceCount,
  1092. 1,
  1093. AddressFile->AddressLock);
  1094. } /* IpxRefAddressFile */
  1095. VOID
  1096. IpxRefAddressFileLock(
  1097. IN PADDRESS_FILE AddressFile
  1098. )
  1099. /*++
  1100. Routine Description:
  1101. This routine increments the reference count on an address file.
  1102. IT IS CALLED WITH THE ADDRESS LOCK HELD.
  1103. Arguments:
  1104. AddressFile - Pointer to a transport address file object.
  1105. Return Value:
  1106. none.
  1107. --*/
  1108. {
  1109. CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
  1110. //++AddressFile->ReferenceCount;
  1111. (VOID)InterlockedIncrement(&AddressFile->ReferenceCount);
  1112. } /* IpxRefAddressFileLock */
  1113. VOID
  1114. IpxRefAddressFileSync(
  1115. IN PADDRESS_FILE AddressFile
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. This routine increments the reference count on an address file.
  1120. Arguments:
  1121. AddressFile - Pointer to a transport address file object.
  1122. Return Value:
  1123. none.
  1124. --*/
  1125. {
  1126. CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
  1127. (VOID)IPX_ADD_ULONG (
  1128. &AddressFile->ReferenceCount,
  1129. 1,
  1130. AddressFile->AddressLock);
  1131. } /* IpxRefAddressFileSync */
  1132. VOID
  1133. IpxDerefAddressFile(
  1134. IN PADDRESS_FILE AddressFile
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. This routine dereferences an address file by decrementing the
  1139. reference count contained in the structure. If, after being
  1140. decremented, the reference count is zero, then this routine calls
  1141. IpxDestroyAddressFile to remove it from the system.
  1142. Arguments:
  1143. AddressFile - Pointer to a transport address file object.
  1144. Return Value:
  1145. none.
  1146. --*/
  1147. {
  1148. ULONG oldvalue;
  1149. oldvalue = IPX_ADD_ULONG (
  1150. &AddressFile->ReferenceCount,
  1151. (ULONG)-1,
  1152. AddressFile->AddressLock);
  1153. //
  1154. // If we have deleted all references to this address file, then we can
  1155. // destroy the object. It is okay to have already released the spin
  1156. // lock at this point because there is no possible way that another
  1157. // stream of execution has access to the address any longer.
  1158. //
  1159. CTEAssert (oldvalue > 0);
  1160. if (oldvalue == 1) {
  1161. IpxDestroyAddressFile (AddressFile);
  1162. }
  1163. } /* IpxDerefAddressFile */
  1164. VOID
  1165. IpxDerefAddressFileSync(
  1166. IN PADDRESS_FILE AddressFile
  1167. )
  1168. /*++
  1169. Routine Description:
  1170. This routine dereferences an address file by decrementing the
  1171. reference count contained in the structure. If, after being
  1172. decremented, the reference count is zero, then this routine calls
  1173. IpxDestroyAddressFile to remove it from the system. This routine
  1174. can only be called when we are synchronized (inside an IPX_SYNC_START/
  1175. IPX_SYNC_END pair, with a lock held, or in an indication).
  1176. Arguments:
  1177. AddressFile - Pointer to a transport address file object.
  1178. Return Value:
  1179. none.
  1180. --*/
  1181. {
  1182. ULONG oldvalue;
  1183. oldvalue = IPX_ADD_ULONG (
  1184. &AddressFile->ReferenceCount,
  1185. (ULONG)-1,
  1186. AddressFile->AddressLock);
  1187. //
  1188. // If we have deleted all references to this address file, then we can
  1189. // destroy the object. It is okay to have already released the spin
  1190. // lock at this point because there is no possible way that another
  1191. // stream of execution has access to the address any longer.
  1192. //
  1193. CTEAssert (oldvalue > 0);
  1194. if (oldvalue == 1) {
  1195. IpxDestroyAddressFile (AddressFile);
  1196. }
  1197. } /* IpxDerefAddressFileSync */
  1198. #endif
  1199. PADDRESS
  1200. IpxLookupAddress(
  1201. IN PDEVICE Device,
  1202. IN USHORT Socket
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. This routine scans the transport addresses defined for the given
  1207. device context and compares them with the specified NETWORK
  1208. NAME values. If an exact match is found, then a pointer to the
  1209. ADDRESS object is returned, and as a side effect, the reference
  1210. count to the address object is incremented. If the address is not
  1211. found, then NULL is returned.
  1212. NOTE: This routine must be called with the Device
  1213. spinlock held.
  1214. Arguments:
  1215. Device - Pointer to the device object and its extension.
  1216. Socket - The socket to look up.
  1217. Return Value:
  1218. Pointer to the ADDRESS object found, or NULL if not found.
  1219. --*/
  1220. {
  1221. PADDRESS Address;
  1222. PLIST_ENTRY p;
  1223. ULONG Hash = IPX_HASH_SOCKET (Socket);
  1224. p = Device->AddressDatabases[Hash].Flink;
  1225. for (p = Device->AddressDatabases[Hash].Flink;
  1226. p != &Device->AddressDatabases[Hash];
  1227. p = p->Flink) {
  1228. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  1229. if (Address->Stopping) {
  1230. continue;
  1231. }
  1232. if (Address->Socket == Socket) {
  1233. //
  1234. // We found the match. Bump the reference count on the address, and
  1235. // return a pointer to the address object for the caller to use.
  1236. //
  1237. IpxReferenceAddressLock (Address, AREF_LOOKUP);
  1238. return Address;
  1239. }
  1240. }
  1241. //
  1242. // The specified address was not found.
  1243. //
  1244. return NULL;
  1245. } /* IpxLookupAddress */
  1246. NTSTATUS
  1247. IpxStopAddressFile(
  1248. IN PADDRESS_FILE AddressFile
  1249. )
  1250. /*++
  1251. Routine Description:
  1252. This routine is called to terminate all activity on an AddressFile and
  1253. destroy the object. We remove every connection and datagram associated
  1254. with this addressfile from the address database and terminate their
  1255. activity. Then, if there are no other outstanding addressfiles open on
  1256. this address, the address will go away.
  1257. Arguments:
  1258. AddressFile - pointer to the addressFile to be stopped
  1259. Return Value:
  1260. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the request
  1261. is not for a real address.
  1262. --*/
  1263. {
  1264. CTELockHandle LockHandle;
  1265. PREQUEST Request;
  1266. PADDRESS Address = AddressFile->Address;
  1267. PLIST_ENTRY p;
  1268. KIRQL irql;
  1269. IoAcquireCancelSpinLock( &irql );
  1270. CTEGetLock (&Address->Lock, &LockHandle);
  1271. if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) {
  1272. CTEFreeLock (&Address->Lock, LockHandle);
  1273. IoReleaseCancelSpinLock( irql );
  1274. return STATUS_SUCCESS;
  1275. }
  1276. AddressFile->State = ADDRESSFILE_STATE_CLOSING;
  1277. while (!(IsListEmpty(&AddressFile->ReceiveDatagramQueue))) {
  1278. p = RemoveHeadList (&AddressFile->ReceiveDatagramQueue);
  1279. Request = LIST_ENTRY_TO_REQUEST (p);
  1280. REQUEST_INFORMATION(Request) = 0;
  1281. REQUEST_STATUS(Request) = STATUS_NETWORK_NAME_DELETED;
  1282. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1283. CTEFreeLock(&Address->Lock, LockHandle);
  1284. IoReleaseCancelSpinLock( irql );
  1285. IpxCompleteRequest (Request);
  1286. IpxFreeRequest (Device, Request);
  1287. IpxDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);
  1288. IoAcquireCancelSpinLock( &irql );
  1289. CTEGetLock(&Address->Lock, &LockHandle);
  1290. }
  1291. CTEFreeLock(&Address->Lock, LockHandle);
  1292. IoReleaseCancelSpinLock( irql );
  1293. return STATUS_SUCCESS;
  1294. } /* IpxStopAddressFile */
  1295. NTSTATUS
  1296. IpxCloseAddressFile(
  1297. IN PDEVICE Device,
  1298. IN PREQUEST Request
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This routine is called to close the addressfile pointed to by a file
  1303. object. If there is any activity to be run down, we will run it down
  1304. before we terminate the addressfile. We remove every connection and
  1305. datagram associated with this addressfile from the address database
  1306. and terminate their activity. Then, if there are no other outstanding
  1307. addressfiles open on this address, the address will go away.
  1308. Arguments:
  1309. Request - the close request.
  1310. Return Value:
  1311. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the
  1312. request does not point to a real address.
  1313. --*/
  1314. {
  1315. PADDRESS Address;
  1316. PADDRESS_FILE AddressFile;
  1317. CTELockHandle LockHandle;
  1318. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  1319. AddressFile->CloseRequest = Request;
  1320. //
  1321. // We assume that addressFile has already been verified
  1322. // at this point.
  1323. //
  1324. Address = AddressFile->Address;
  1325. CTEAssert (Address);
  1326. //
  1327. // Remove us from the access info for this address.
  1328. //
  1329. KeEnterCriticalRegion();
  1330. ExAcquireResourceExclusiveLite (&Device->AddressResource, TRUE);
  1331. #ifdef ISN_NT
  1332. IoRemoveShareAccess (AddressFile->FileObject, &Address->u.ShareAccess);
  1333. #endif
  1334. ExReleaseResourceLite (&Device->AddressResource);
  1335. KeLeaveCriticalRegion();
  1336. //
  1337. // If this address file had broadcasts enabled, turn it off.
  1338. //
  1339. //
  1340. // Not needed anymore
  1341. //
  1342. /*
  1343. CTEGetLock (&Device->Lock, &LockHandle);
  1344. if (AddressFile->EnableBroadcast) {
  1345. AddressFile->EnableBroadcast = FALSE;
  1346. IpxRemoveBroadcast (Device);
  1347. }
  1348. CTEFreeLock (&Device->Lock, LockHandle);
  1349. */
  1350. IpxStopAddressFile (AddressFile);
  1351. IpxDereferenceAddressFile (AddressFile, AFREF_CREATE);
  1352. return STATUS_PENDING;
  1353. } /* IpxCloseAddressFile */