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.

1786 lines
40 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. spxaddr.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. Author:
  10. Adam Barr (adamba ) Original Version
  11. Nikhil Kamkolkar (nikhilk) 11-November-1993
  12. Environment:
  13. Kernel mode
  14. Revision History:
  15. --*/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #ifdef ALLOC_PRAGMA
  19. //#pragma alloc_text( PAGE, SpxAddrFileCreate)
  20. #pragma alloc_text( PAGE, SpxAddrFileClose)
  21. #endif
  22. // Define module number for event logging entries
  23. #define FILENUM SPXADDR
  24. // Map all generic accesses to the same one.
  25. static GENERIC_MAPPING AddressGenericMapping =
  26. { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  27. #define REORDER(_Socket) ((((_Socket) & 0xff00) >> 8) | (((_Socket) & 0x00ff) << 8))
  28. NTSTATUS
  29. SpxAddrOpen(
  30. IN PDEVICE Device,
  31. IN PREQUEST Request
  32. )
  33. /*++
  34. Routine Description:
  35. This routine opens a file that points to an existing address object, or, if
  36. the object doesn't exist, creates it (note that creation of the address
  37. object includes registering the address, and may take many seconds to
  38. complete, depending upon system configuration).
  39. If the address already exists, and it has an ACL associated with it, the
  40. ACL is checked for access rights before allowing creation of the address.
  41. Arguments:
  42. DeviceObject - pointer to the device object describing the ST transport.
  43. Request - a pointer to the request used for the creation of the address.
  44. Return Value:
  45. NTSTATUS - status of operation.
  46. --*/
  47. {
  48. NTSTATUS status;
  49. PSPX_ADDR pAddr;
  50. PSPX_ADDR_FILE pAddrFile;
  51. PFILE_FULL_EA_INFORMATION ea;
  52. TRANSPORT_ADDRESS UNALIGNED *name;
  53. TA_ADDRESS * AddressName;
  54. USHORT Socket, hostSocket;
  55. ULONG DesiredShareAccess;
  56. CTELockHandle LockHandle, LockHandleAddr;
  57. PACCESS_STATE AccessState;
  58. ACCESS_MASK GrantedAccess;
  59. BOOLEAN AccessAllowed;
  60. int i;
  61. BOOLEAN found = FALSE;
  62. INT Size = 0;
  63. #ifdef ISN_NT
  64. PIRP Irp = (PIRP)Request;
  65. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  66. #endif
  67. // The network name is in the EA, passed in the request.
  68. ea = OPEN_REQUEST_EA_INFORMATION(Request);
  69. if (ea == NULL)
  70. {
  71. DBGPRINT(TDI, ERR,
  72. ("OpenAddress: REQUEST %lx has no EA\n", Request));
  73. return STATUS_NONEXISTENT_EA_ENTRY;
  74. }
  75. // this may be a valid name; parse the name from the EA and use it if OK.
  76. name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
  77. if (ea->EaValueLength < (sizeof(TRANSPORT_ADDRESS) -1)) {
  78. DBGPRINT(TDI, ERR, ("The ea value length does not match the TA address length\n"));
  79. DbgPrint("IPX: STATUS_INVALID_EA_NAME - 1\n");
  80. return STATUS_INVALID_EA_NAME;
  81. }
  82. AddressName = (PTA_ADDRESS)&name->Address[0];
  83. Size = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) + FIELD_OFFSET(TA_ADDRESS, Address) + AddressName->AddressLength;
  84. //
  85. // The name can be passed with multiple entries; we'll take and use only
  86. // the first one of type IPX.
  87. //
  88. //DbgPrint("Size (%d) & EaValueLength (%d)", Size, ea->EaValueLength);
  89. if (Size > ea->EaValueLength) {
  90. DbgPrint("EA:%lx, Name:%lx, AddressName:%lx\n", ea, name, AddressName);
  91. CTEAssert(FALSE);
  92. }
  93. // The name can be passed with multiple entries; we'll take and use only
  94. // the first one of type IPX.
  95. for (i=0;i<name->TAAddressCount;i++)
  96. {
  97. if (Size > ea->EaValueLength) {
  98. DBGPRINT(TDI, ERR, ("The EA value length does not match the TA address length (2)\n"));
  99. DbgPrint("IPX: STATUS_INVALID_EA_NAME - 2\n");
  100. return STATUS_INVALID_EA_NAME;
  101. }
  102. if (AddressName->AddressType == TDI_ADDRESS_TYPE_IPX)
  103. {
  104. if (AddressName->AddressLength >= sizeof(TDI_ADDRESS_IPX))
  105. {
  106. Socket =
  107. ((TDI_ADDRESS_IPX UNALIGNED *)&AddressName->Address[0])->Socket;
  108. GETSHORT2SHORT(&hostSocket, &Socket);
  109. DBGPRINT(CREATE, DBG,
  110. ("SpxAddrOpen: Creating socket %lx.h%lx\n",
  111. Socket, hostSocket ));
  112. found = TRUE;
  113. }
  114. break;
  115. }
  116. else
  117. {
  118. AddressName = (PTA_ADDRESS)(AddressName->Address +
  119. AddressName->AddressLength);
  120. Size += FIELD_OFFSET(TA_ADDRESS, Address);
  121. if (Size < ea->EaValueLength) {
  122. Size += AddressName->AddressLength;
  123. } else {
  124. break;
  125. }
  126. }
  127. }
  128. if (!found)
  129. {
  130. DBGPRINT(TDI, ERR,
  131. ("OpenAddress: REQUEST %lx has no IPX Address\n", Request));
  132. return STATUS_INVALID_ADDRESS_COMPONENT;
  133. }
  134. #ifdef SOCKET_RANGE_OPEN_LIMITATION_REMOVED
  135. // Is the socket in our range if its in the range 0x4000-0x7FFF
  136. if (IN_RANGE(hostSocket, DYNSKT_RANGE_START, DYNSKT_RANGE_END))
  137. {
  138. if (!IN_RANGE(
  139. hostSocket,
  140. PARAM(CONFIG_SOCKET_RANGE_START),
  141. PARAM(CONFIG_SOCKET_RANGE_END)))
  142. {
  143. return(STATUS_INVALID_ADDRESS);
  144. }
  145. }
  146. #endif
  147. // get an address file structure to represent this address.
  148. status = SpxAddrFileCreate(Device, Request, &pAddrFile);
  149. if (!NT_SUCCESS(status))
  150. return status;
  151. // See if this address is already established. This call automatically
  152. // increments the reference count on the address so that it won't disappear
  153. // from underneath us after this call but before we have a chance to use it.
  154. //
  155. // To ensure that we don't create two address objects for the
  156. // same address, we hold the device context addressResource until
  157. // we have found the address or created a new one.
  158. KeEnterCriticalRegion();
  159. ExAcquireResourceExclusiveLite (&Device->dev_AddrResource, TRUE);
  160. CTEGetLock (&Device->dev_Lock, &LockHandle);
  161. // We checkfor/create sockets within the critical section.
  162. if (Socket == 0)
  163. {
  164. Socket = SpxAddrAssignSocket(Device);
  165. if (Socket == 0)
  166. {
  167. DBGPRINT(ADDRESS, ERR,
  168. ("OpenAddress, no unique socket found\n"));
  169. CTEFreeLock (&Device->dev_Lock, LockHandle);
  170. ExReleaseResourceLite (&Device->dev_AddrResource);
  171. SpxAddrFileDestroy(pAddrFile);
  172. return STATUS_INSUFFICIENT_RESOURCES;
  173. }
  174. DBGPRINT(ADDRESS, INFO,
  175. ("OpenAddress, assigned socket %lx\n", Socket));
  176. }
  177. pAddr = SpxAddrLookup(Device, Socket);
  178. if (pAddr == NULL)
  179. {
  180. CTEFreeLock (&Device->dev_Lock, LockHandle);
  181. // This address doesn't exist. Create it.
  182. // registering it. It also puts a ref of type ADDR_FILE on address.
  183. pAddr = SpxAddrCreate(
  184. Device,
  185. Socket);
  186. if (pAddr != (PSPX_ADDR)NULL)
  187. {
  188. #ifdef ISN_NT
  189. // Initialize the shared access now. We use read access
  190. // to control all access.
  191. DesiredShareAccess = (ULONG)
  192. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  193. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  194. FILE_SHARE_READ : 0);
  195. IoSetShareAccess(
  196. FILE_READ_DATA,
  197. DesiredShareAccess,
  198. IrpSp->FileObject,
  199. &pAddr->u.sa_ShareAccess);
  200. // Assign the security descriptor (need to do this with
  201. // the spinlock released because the descriptor is not
  202. // mapped).
  203. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  204. status = SeAssignSecurity(
  205. NULL, // parent descriptor
  206. AccessState->SecurityDescriptor,
  207. &pAddr->sa_SecurityDescriptor,
  208. FALSE, // is directory
  209. &AccessState->SubjectSecurityContext,
  210. &AddressGenericMapping,
  211. NonPagedPool);
  212. if (!NT_SUCCESS(status))
  213. {
  214. // Error, return status.
  215. IoRemoveShareAccess (IrpSp->FileObject, &pAddr->u.sa_ShareAccess);
  216. ExReleaseResourceLite (&Device->dev_AddrResource);
  217. KeLeaveCriticalRegion();
  218. SpxAddrDereference (pAddr, AREF_ADDR_FILE);
  219. SpxAddrFileDestroy(pAddrFile);
  220. return status;
  221. }
  222. #endif
  223. ExReleaseResourceLite (&Device->dev_AddrResource);
  224. KeLeaveCriticalRegion();
  225. // if the adapter isn't ready, we can't do any of this; get out
  226. #if defined(_PNP_POWER)
  227. if (Device->dev_State != DEVICE_STATE_OPEN)
  228. #else
  229. if (Device->dev_State == DEVICE_STATE_STOPPING)
  230. #endif _PNP_POWER
  231. {
  232. SpxAddrDereference (pAddr, AREF_ADDR_FILE);
  233. SpxAddrFileDestroy(pAddrFile);
  234. status = STATUS_DEVICE_NOT_READY;
  235. }
  236. else
  237. {
  238. REQUEST_OPEN_CONTEXT(Request) = (PVOID)pAddrFile;
  239. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  240. #ifdef ISN_NT
  241. pAddrFile->saf_FileObject = IrpSp->FileObject;
  242. #endif
  243. CTEGetLock (&pAddr->sa_Lock, &LockHandleAddr);
  244. pAddrFile->saf_Addr = pAddr;
  245. pAddrFile->saf_AddrLock = &pAddr->sa_Lock;
  246. // Set flags appropriately, note spx/stream flags are set at this
  247. // point.
  248. pAddrFile->saf_Flags &= ~SPX_ADDRFILE_OPENING;
  249. pAddrFile->saf_Flags |= SPX_ADDRFILE_OPEN;
  250. // Queue in the address list, removed in destroy.
  251. pAddrFile->saf_Next = pAddr->sa_AddrFileList;
  252. pAddr->sa_AddrFileList = pAddrFile;
  253. CTEFreeLock (&pAddr->sa_Lock, LockHandleAddr);
  254. status = STATUS_SUCCESS;
  255. }
  256. }
  257. else
  258. {
  259. ExReleaseResourceLite (&Device->dev_AddrResource);
  260. KeLeaveCriticalRegion();
  261. // If the address could not be created, and is not in the process of
  262. // being created, then we can't open up an address.
  263. SpxAddrFileDestroy(pAddrFile);
  264. status = STATUS_INSUFFICIENT_RESOURCES;
  265. }
  266. }
  267. else
  268. {
  269. CTEFreeLock (&Device->dev_Lock, LockHandle);
  270. DBGPRINT(ADDRESS, ERR,
  271. ("Add to address %lx\n", pAddr));
  272. // The address already exists. Check the ACL and see if we
  273. // can access it. If so, simply use this address as our address.
  274. #ifdef ISN_NT
  275. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  276. AccessAllowed = SeAccessCheck(
  277. pAddr->sa_SecurityDescriptor,
  278. &AccessState->SubjectSecurityContext,
  279. FALSE, // tokens locked
  280. IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
  281. (ACCESS_MASK)0, // previously granted
  282. NULL, // privileges
  283. &AddressGenericMapping,
  284. Irp->RequestorMode,
  285. &GrantedAccess,
  286. &status);
  287. #else // ISN_NT
  288. AccessAllowed = TRUE;
  289. #endif // ISN_NT
  290. if (!AccessAllowed)
  291. {
  292. ExReleaseResourceLite (&Device->dev_AddrResource);
  293. KeLeaveCriticalRegion();
  294. SpxAddrFileDestroy(pAddrFile);
  295. }
  296. else
  297. {
  298. #ifdef ISN_NT
  299. // Now check that we can obtain the desired share
  300. // access. We use read access to control all access.
  301. DesiredShareAccess = (ULONG)
  302. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  303. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  304. FILE_SHARE_READ : 0);
  305. status = IoCheckShareAccess(
  306. FILE_READ_DATA,
  307. DesiredShareAccess,
  308. IrpSp->FileObject,
  309. &pAddr->u.sa_ShareAccess,
  310. TRUE);
  311. #else // ISN_NT
  312. status = STATUS_SUCCESS;
  313. #endif // ISN_NT
  314. if (!NT_SUCCESS (status))
  315. {
  316. ExReleaseResourceLite (&Device->dev_AddrResource);
  317. KeLeaveCriticalRegion();
  318. SpxAddrFileDestroy(pAddrFile);
  319. }
  320. else
  321. {
  322. ExReleaseResourceLite (&Device->dev_AddrResource);
  323. KeLeaveCriticalRegion();
  324. CTEGetLock (&Device->dev_Lock, &LockHandle);
  325. CTEGetLock (&pAddr->sa_Lock, &LockHandleAddr);
  326. pAddrFile->saf_Addr = pAddr;
  327. pAddrFile->saf_AddrLock = &pAddr->sa_Lock;
  328. #ifdef ISN_NT
  329. pAddrFile->saf_FileObject = IrpSp->FileObject;
  330. #endif
  331. // Set flags appropriately, note spx/stream flags are set at this
  332. // point.
  333. pAddrFile->saf_Flags &= ~SPX_ADDRFILE_OPENING;
  334. pAddrFile->saf_Flags |= SPX_ADDRFILE_OPEN;
  335. SpxAddrLockReference (pAddr, AREF_ADDR_FILE);
  336. REQUEST_OPEN_CONTEXT(Request) = (PVOID)pAddrFile;
  337. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  338. // Queue in the address list, removed in destroy.
  339. pAddrFile->saf_Next = pAddr->sa_AddrFileList;
  340. pAddr->sa_AddrFileList = pAddrFile;
  341. CTEFreeLock (&pAddr->sa_Lock, LockHandleAddr);
  342. CTEFreeLock (&Device->dev_Lock, LockHandle);
  343. status = STATUS_SUCCESS;
  344. }
  345. }
  346. // Remove the reference from SpxLookupAddress.
  347. SpxAddrDereference (pAddr, AREF_LOOKUP);
  348. }
  349. return status;
  350. } // SpxAddrOpen
  351. NTSTATUS
  352. SpxAddrSetEventHandler(
  353. IN PDEVICE Device,
  354. IN PREQUEST pRequest
  355. )
  356. {
  357. CTELockHandle lockHandle;
  358. NTSTATUS status = STATUS_SUCCESS;
  359. PSPX_ADDR_FILE
  360. pSpxAddrFile = (PSPX_ADDR_FILE)REQUEST_OPEN_CONTEXT(pRequest);
  361. PTDI_REQUEST_KERNEL_SET_EVENT
  362. pParam = (PTDI_REQUEST_KERNEL_SET_EVENT)REQUEST_PARAMETERS(pRequest);
  363. if ((status = SpxAddrFileVerify(pSpxAddrFile)) != STATUS_SUCCESS)
  364. return(status);
  365. CTEGetLock(pSpxAddrFile->saf_AddrLock, &lockHandle);
  366. switch (pParam->EventType)
  367. {
  368. case TDI_EVENT_ERROR:
  369. break;
  370. case TDI_EVENT_CONNECT:
  371. pSpxAddrFile->saf_ConnHandler =
  372. (PTDI_IND_CONNECT)(pParam->EventHandler);
  373. pSpxAddrFile->saf_ConnHandlerCtx =
  374. pParam->EventContext;
  375. break;
  376. case TDI_EVENT_RECEIVE:
  377. pSpxAddrFile->saf_RecvHandler =
  378. (PTDI_IND_RECEIVE)(pParam->EventHandler);
  379. pSpxAddrFile->saf_RecvHandlerCtx =
  380. pParam->EventContext;
  381. break;
  382. case TDI_EVENT_DISCONNECT:
  383. pSpxAddrFile->saf_DiscHandler =
  384. (PTDI_IND_DISCONNECT)(pParam->EventHandler);
  385. pSpxAddrFile->saf_DiscHandlerCtx =
  386. pParam->EventContext;
  387. break;
  388. case TDI_EVENT_SEND_POSSIBLE :
  389. pSpxAddrFile->saf_SendPossibleHandler =
  390. (PTDI_IND_SEND_POSSIBLE)(pParam->EventHandler);
  391. pSpxAddrFile->saf_SendPossibleHandlerCtx =
  392. pParam->EventContext;
  393. break;
  394. case TDI_EVENT_RECEIVE_DATAGRAM:
  395. case TDI_EVENT_RECEIVE_EXPEDITED:
  396. default:
  397. status = STATUS_INVALID_PARAMETER;
  398. }
  399. CTEFreeLock(pSpxAddrFile->saf_AddrLock, lockHandle);
  400. SpxAddrFileDereference(pSpxAddrFile, AFREF_VERIFY);
  401. return(status);
  402. }
  403. PSPX_ADDR
  404. SpxAddrCreate(
  405. IN PDEVICE Device,
  406. IN USHORT Socket
  407. )
  408. /*++
  409. Routine Description:
  410. This routine creates a transport address and associates it with
  411. the specified transport device context. The reference count in the
  412. address is automatically set to 1, and the reference count of the
  413. device context is incremented.
  414. NOTE: This routine must be called with the Device
  415. spinlock held.
  416. Arguments:
  417. Device - Pointer to the device context (which is really just
  418. the device object with its extension) to be associated with the
  419. address.
  420. Socket - The socket to assign to this address.
  421. Return Value:
  422. The newly created address, or NULL if none can be allocated.
  423. --*/
  424. {
  425. PSPX_ADDR pAddr;
  426. int index;
  427. CTELockHandle lockHandle;
  428. pAddr = (PSPX_ADDR)SpxAllocateZeroedMemory (sizeof(SPX_ADDR));
  429. if (pAddr == NULL)
  430. {
  431. DBGPRINT(ADDRESS, INFO,
  432. ("Create address %lx failed\n", (ULONG)Socket));
  433. return NULL;
  434. }
  435. DBGPRINT(ADDRESS, INFO,
  436. ("Create address %lx (%lx)\n", pAddr, (ULONG)Socket));
  437. pAddr->sa_Type = SPX_ADDRESS_SIGNATURE;
  438. pAddr->sa_Size = sizeof (SPX_ADDR);
  439. pAddr->sa_Flags = 0;
  440. pAddr->sa_Device = Device;
  441. pAddr->sa_DeviceLock = &Device->dev_Lock;
  442. CTEInitLock (&pAddr->sa_Lock);
  443. // This reference is for the address file that will associated with this addr.
  444. pAddr->sa_RefCount = 1;
  445. #if DBG
  446. pAddr->sa_RefTypes[AREF_ADDR_FILE] = 1;
  447. #endif
  448. pAddr->sa_Socket = Socket;
  449. // Insert address into the device hash table.
  450. index = (int)(Socket & NUM_SPXADDR_HASH_MASK);
  451. CTEGetLock (&Device->dev_Lock, &lockHandle);
  452. pAddr->sa_Next = Device->dev_AddrHashTable[index];
  453. Device->dev_AddrHashTable[index] = pAddr;
  454. CTEFreeLock (&Device->dev_Lock, lockHandle);
  455. SpxReferenceDevice (Device, DREF_ADDRESS);
  456. return pAddr;
  457. } // SpxAddrCreate
  458. NTSTATUS
  459. SpxAddrFileVerify(
  460. IN PSPX_ADDR_FILE pAddrFile
  461. )
  462. /*++
  463. Routine Description:
  464. This routine is called to verify that the pointer given us in a file
  465. object is in fact a valid address file object. We also verify that the
  466. address object pointed to by it is a valid address object, and reference
  467. it to keep it from disappearing while we use it.
  468. Arguments:
  469. AddressFile - potential pointer to a SPX_ADDR_FILE object
  470. Return Value:
  471. STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
  472. --*/
  473. {
  474. CTELockHandle LockHandle;
  475. NTSTATUS status = STATUS_SUCCESS;
  476. PSPX_ADDR Address;
  477. // try to verify the address file signature. If the signature is valid,
  478. // verify the address pointed to by it and get the address spinlock.
  479. // check the address's state, and increment the reference count if it's
  480. // ok to use it. Note that the only time we return an error for state is
  481. // if the address is closing.
  482. try
  483. {
  484. if ((pAddrFile->saf_Size == sizeof (SPX_ADDR_FILE)) &&
  485. (pAddrFile->saf_Type == SPX_ADDRESSFILE_SIGNATURE) )
  486. {
  487. Address = pAddrFile->saf_Addr;
  488. if ((Address->sa_Size == sizeof (SPX_ADDR)) &&
  489. (Address->sa_Type == SPX_ADDRESS_SIGNATURE) )
  490. {
  491. CTEGetLock (&Address->sa_Lock, &LockHandle);
  492. if ((Address->sa_Flags & SPX_ADDR_CLOSING) == 0)
  493. {
  494. SpxAddrFileLockReference(pAddrFile, AFREF_VERIFY);
  495. }
  496. else
  497. {
  498. DBGPRINT(TDI, ERR,
  499. ("StVerifyAddressFile: A %lx closing\n", Address));
  500. status = STATUS_INVALID_ADDRESS;
  501. }
  502. CTEFreeLock (&Address->sa_Lock, LockHandle);
  503. }
  504. else
  505. {
  506. DBGPRINT(TDI, ERR,
  507. ("StVerifyAddressFile: A %lx bad signature\n", Address));
  508. status = STATUS_INVALID_ADDRESS;
  509. }
  510. }
  511. else
  512. {
  513. DBGPRINT(TDI, ERR,
  514. ("StVerifyAddressFile: AF %lx bad signature\n", pAddrFile));
  515. status = STATUS_INVALID_ADDRESS;
  516. }
  517. } except(EXCEPTION_EXECUTE_HANDLER) {
  518. DBGPRINT(TDI, ERR,
  519. ("SpxAddrFileVerify: AF %lx exception\n", Address));
  520. return GetExceptionCode();
  521. }
  522. return status;
  523. } // SpxAddrFileVerify
  524. VOID
  525. SpxAddrDestroy(
  526. IN PVOID Parameter
  527. )
  528. /*++
  529. Routine Description:
  530. This routine destroys a transport address and removes all references
  531. made by it to other objects in the transport. The address structure
  532. is returned to nonpaged system pool. It is assumed
  533. that the caller has already removed all addressfile structures associated
  534. with this address.
  535. It is called from a worker thread queue by SpxDerefAddress when
  536. the reference count goes to 0.
  537. This thread is only queued by SpxDerefAddress. The reason for
  538. this is that there may be multiple streams of execution which are
  539. simultaneously referencing the same address object, and it should
  540. not be deleted out from under an interested stream of execution.
  541. Arguments:
  542. Address - Pointer to a transport address structure to be destroyed.
  543. Return Value:
  544. NTSTATUS - status of operation.
  545. --*/
  546. {
  547. PSPX_ADDR pAddr, *ppAddr;
  548. CTELockHandle LockHandle;
  549. PSPX_ADDR Address = (PSPX_ADDR)Parameter;
  550. PDEVICE Device = Address->sa_Device;
  551. int index = (int)(Address->sa_Socket & NUM_SPXADDR_HASH_MASK);
  552. DBGPRINT(ADDRESS, INFO,
  553. ("Destroy address %lx\n", Address));
  554. SeDeassignSecurity (&Address->sa_SecurityDescriptor);
  555. // Delink this address from its associated device context's address
  556. // database. To do this we must spin lock on the device context object,
  557. // not on the address.
  558. CTEGetLock (&Device->dev_Lock, &LockHandle);
  559. for (ppAddr = &Device->dev_AddrHashTable[index]; (pAddr = *ppAddr) != NULL;)
  560. {
  561. if (pAddr == Address)
  562. {
  563. *ppAddr = pAddr->sa_Next;
  564. break;
  565. }
  566. ppAddr = &pAddr->sa_Next;
  567. }
  568. CTEFreeLock (&Device->dev_Lock, LockHandle);
  569. SpxFreeMemory (Address);
  570. SpxDereferenceDevice (Device, DREF_ADDRESS);
  571. }
  572. #if DBG
  573. VOID
  574. SpxAddrRef(
  575. IN PSPX_ADDR Address
  576. )
  577. /*++
  578. Routine Description:
  579. This routine increments the reference count on a transport address.
  580. Arguments:
  581. Address - Pointer to a transport address object.
  582. Return Value:
  583. none.
  584. --*/
  585. {
  586. CTEAssert (Address->sa_RefCount > 0); // not perfect, but...
  587. (VOID)SPX_ADD_ULONG (
  588. &Address->sa_RefCount,
  589. 1,
  590. Address->sa_DeviceLock);
  591. }
  592. VOID
  593. SpxAddrLockRef(
  594. IN PSPX_ADDR Address
  595. )
  596. /*++
  597. Routine Description:
  598. This routine increments the reference count on a transport address
  599. when the device lock is already held.
  600. Arguments:
  601. Address - Pointer to a transport address object.
  602. Return Value:
  603. none.
  604. --*/
  605. {
  606. CTEAssert (Address->sa_RefCount > 0); // not perfect, but...
  607. (VOID)SPX_ADD_ULONG (
  608. &Address->sa_RefCount,
  609. 1,
  610. Address->sa_DeviceLock);
  611. }
  612. #endif
  613. VOID
  614. SpxAddrDeref(
  615. IN PSPX_ADDR Address
  616. )
  617. /*++
  618. Routine Description:
  619. This routine dereferences a transport address by decrementing the
  620. reference count contained in the structure. If, after being
  621. decremented, the reference count is zero, then this routine calls
  622. SpxDestroyAddress to remove it from the system.
  623. Arguments:
  624. Address - Pointer to a transport address object.
  625. Return Value:
  626. none.
  627. --*/
  628. {
  629. ULONG oldvalue;
  630. oldvalue = SPX_ADD_ULONG (
  631. &Address->sa_RefCount,
  632. (ULONG)-1,
  633. Address->sa_DeviceLock);
  634. //
  635. // If we have deleted all references to this address, then we can
  636. // destroy the object. It is okay to have already released the spin
  637. // lock at this point because there is no possible way that another
  638. // stream of execution has access to the address any longer.
  639. //
  640. CTEAssert (oldvalue != 0);
  641. if (oldvalue == 1)
  642. {
  643. #if ISN_NT
  644. ExInitializeWorkItem(
  645. &Address->u.sa_DestroyAddrQueueItem,
  646. SpxAddrDestroy,
  647. (PVOID)Address);
  648. ExQueueWorkItem(&Address->u.sa_DestroyAddrQueueItem, DelayedWorkQueue);
  649. #else
  650. SpxAddrDestroy(Address);
  651. #endif
  652. }
  653. }
  654. NTSTATUS
  655. SpxAddrFileCreate(
  656. IN PDEVICE Device,
  657. IN PREQUEST Request,
  658. OUT PSPX_ADDR_FILE * ppAddrFile
  659. )
  660. /*++
  661. Routine Description:
  662. This routine creates an address file from the pool of ther
  663. specified device context. The reference count in the
  664. address is automatically set to 1.
  665. Arguments:
  666. Device - Pointer to the device context (which is really just
  667. the device object with its extension) to be associated with the
  668. address.
  669. Return Value:
  670. The allocate address file or NULL.
  671. --*/
  672. {
  673. NTSTATUS status;
  674. BYTE socketType;
  675. CTELockHandle LockHandle;
  676. PSPX_ADDR_FILE pAddrFile;
  677. // What is the address file type?
  678. if (!NT_SUCCESS(status = SpxUtilGetSocketType(
  679. REQUEST_OPEN_NAME(Request),
  680. &socketType)))
  681. {
  682. return(status);
  683. }
  684. pAddrFile = (PSPX_ADDR_FILE)SpxAllocateZeroedMemory (sizeof(SPX_ADDR_FILE));
  685. if (pAddrFile == NULL)
  686. {
  687. DBGPRINT(ADDRESS, ERR,
  688. ("Create address file failed\n"));
  689. return STATUS_INSUFFICIENT_RESOURCES;
  690. }
  691. DBGPRINT(ADDRESS, INFO,
  692. ("Create address file %lx\n", pAddrFile));
  693. CTEGetLock (&Device->dev_Lock, &LockHandle);
  694. pAddrFile->saf_Type = SPX_ADDRESSFILE_SIGNATURE;
  695. pAddrFile->saf_Size = sizeof (SPX_ADDR_FILE);
  696. pAddrFile->saf_Addr = NULL;
  697. #ifdef ISN_NT
  698. pAddrFile->saf_FileObject = NULL;
  699. #endif
  700. pAddrFile->saf_Device = Device;
  701. pAddrFile->saf_Flags = SPX_ADDRFILE_OPENING;
  702. if ((socketType == SOCKET1_TYPE_SEQPKT) ||
  703. (socketType == SOCKET1_TYPE_STREAM))
  704. {
  705. if (socketType == SOCKET1_TYPE_STREAM)
  706. {
  707. pAddrFile->saf_Flags |= SPX_ADDRFILE_STREAM;
  708. }
  709. }
  710. if ((socketType == SOCKET2_TYPE_SEQPKT) ||
  711. (socketType == SOCKET2_TYPE_STREAM))
  712. {
  713. pAddrFile->saf_Flags |= SPX_ADDRFILE_SPX2;
  714. if (socketType == SOCKET2_TYPE_STREAM)
  715. {
  716. pAddrFile->saf_Flags |= SPX_ADDRFILE_STREAM;
  717. }
  718. }
  719. pAddrFile->saf_RefCount = 1;
  720. #if DBG
  721. pAddrFile->saf_RefTypes[AFREF_CREATE] = 1;
  722. #endif
  723. pAddrFile->saf_CloseReq = (PREQUEST)NULL;
  724. // Initialize the request handlers.
  725. pAddrFile->saf_ConnHandler =
  726. pAddrFile->saf_ConnHandlerCtx = NULL;
  727. pAddrFile->saf_DiscHandler =
  728. pAddrFile->saf_DiscHandlerCtx = NULL;
  729. pAddrFile->saf_RecvHandler =
  730. pAddrFile->saf_RecvHandlerCtx = NULL;
  731. pAddrFile->saf_ErrHandler =
  732. pAddrFile->saf_ErrHandlerCtx = NULL;
  733. // Release lock
  734. CTEFreeLock (&Device->dev_Lock, LockHandle);
  735. // Put in the global list for our reference
  736. spxAddrInsertIntoGlobalList(pAddrFile);
  737. *ppAddrFile = pAddrFile;
  738. return STATUS_SUCCESS;
  739. }
  740. NTSTATUS
  741. SpxAddrFileDestroy(
  742. IN PSPX_ADDR_FILE pAddrFile
  743. )
  744. /*++
  745. Routine Description:
  746. This routine destroys an address file and removes all references
  747. made by it to other objects in the transport.
  748. This routine is only called by SpxAddrFileDereference. The reason
  749. for this is that there may be multiple streams of execution which are
  750. simultaneously referencing the same address file object, and it should
  751. not be deleted out from under an interested stream of execution.
  752. Arguments:
  753. pAddrFile Pointer to a transport address file structure to be destroyed.
  754. Return Value:
  755. NTSTATUS - status of operation.
  756. --*/
  757. {
  758. CTELockHandle LockHandle, LockHandle1;
  759. PSPX_ADDR Address;
  760. PDEVICE Device;
  761. PREQUEST CloseRequest;
  762. PSPX_ADDR_FILE pRemAddr, *ppRemAddr;
  763. DBGPRINT(ADDRESS, INFO,
  764. ("Destroy address file %lx\n", pAddrFile));
  765. Address = pAddrFile->saf_Addr;
  766. Device = pAddrFile->saf_Device;
  767. if (Address)
  768. {
  769. CTEGetLock (&Device->dev_Lock, &LockHandle1);
  770. // This addressfile was associated with an address.
  771. CTEGetLock (&Address->sa_Lock, &LockHandle);
  772. // If the last reference on the address is being removed, set the
  773. // closing flag to prevent further references.
  774. //if (Address->sa_RefCount == 1)
  775. //
  776. // ** The lock passed here is a dummy - it is pre-compiled out.
  777. //
  778. if (SPX_ADD_ULONG(&Address->sa_RefCount, 0, &Address->sa_Lock) == 1) {
  779. Address->sa_Flags |= SPX_ADDR_CLOSING;
  780. }
  781. // Dequeue the address file from the address list.
  782. for (ppRemAddr = &Address->sa_AddrFileList; (pRemAddr = *ppRemAddr) != NULL;)
  783. {
  784. if (pRemAddr == pAddrFile)
  785. {
  786. *ppRemAddr = pRemAddr->saf_Next;
  787. break;
  788. }
  789. ppRemAddr = &pRemAddr->saf_Next;
  790. }
  791. pAddrFile->saf_Addr = NULL;
  792. #ifdef ISN_NT
  793. pAddrFile->saf_FileObject->FsContext = NULL;
  794. pAddrFile->saf_FileObject->FsContext2 = NULL;
  795. #endif
  796. CTEFreeLock (&Address->sa_Lock, LockHandle);
  797. CTEFreeLock (&Device->dev_Lock, LockHandle1);
  798. // We will already have been removed from the ShareAccess
  799. // of the owning address.
  800. //
  801. // Now dereference the owning address.
  802. SpxAddrDereference(Address, AREF_ADDR_FILE);
  803. }
  804. // Save this for later completion.
  805. CloseRequest = pAddrFile->saf_CloseReq;
  806. // Remove from the global list
  807. spxAddrRemoveFromGlobalList(pAddrFile);
  808. // return the addressFile to the pool of address files
  809. SpxFreeMemory (pAddrFile);
  810. if (CloseRequest != (PREQUEST)NULL)
  811. {
  812. REQUEST_INFORMATION(CloseRequest) = 0;
  813. REQUEST_STATUS(CloseRequest) = STATUS_SUCCESS;
  814. SpxCompleteRequest (CloseRequest);
  815. SpxFreeRequest (Device, CloseRequest);
  816. }
  817. return STATUS_SUCCESS;
  818. }
  819. #if DBG
  820. VOID
  821. SpxAddrFileRef(
  822. IN PSPX_ADDR_FILE pAddrFile
  823. )
  824. /*++
  825. Routine Description:
  826. This routine increments the reference count on an address file.
  827. Arguments:
  828. pAddrFile - Pointer to a transport address file object.
  829. Return Value:
  830. none.
  831. --*/
  832. {
  833. CTEAssert (pAddrFile->saf_RefCount > 0); // not perfect, but...
  834. (VOID)SPX_ADD_ULONG (
  835. &pAddrFile->saf_RefCount,
  836. 1,
  837. pAddrFile->saf_AddrLock);
  838. } // SpxRefAddressFile
  839. VOID
  840. SpxAddrFileLockRef(
  841. IN PSPX_ADDR_FILE pAddrFile
  842. )
  843. /*++
  844. Routine Description:
  845. This routine increments the reference count on an address file.
  846. IT IS CALLED WITH THE ADDRESS LOCK HELD.
  847. Arguments:
  848. pAddrFile - Pointer to a transport address file object.
  849. Return Value:
  850. none.
  851. --*/
  852. {
  853. CTEAssert (pAddrFile->saf_RefCount > 0); // not perfect, but...
  854. (VOID)SPX_ADD_ULONG (
  855. &pAddrFile->saf_RefCount,
  856. 1,
  857. pAddrFile->saf_AddrLock);
  858. }
  859. #endif
  860. VOID
  861. SpxAddrFileDeref(
  862. IN PSPX_ADDR_FILE pAddrFile
  863. )
  864. /*++
  865. Routine Description:
  866. This routine dereferences an address file by decrementing the
  867. reference count contained in the structure. If, after being
  868. decremented, the reference count is zero, then this routine calls
  869. SpxDestroyAddressFile to remove it from the system.
  870. Arguments:
  871. pAddrFile - Pointer to a transport address file object.
  872. Return Value:
  873. none.
  874. --*/
  875. {
  876. ULONG oldvalue;
  877. oldvalue = SPX_ADD_ULONG (
  878. &pAddrFile->saf_RefCount,
  879. (ULONG)-1,
  880. pAddrFile->saf_AddrLock);
  881. // If we have deleted all references to this address file, then we can
  882. // destroy the object. It is okay to have already released the spin
  883. // lock at this point because there is no possible way that another
  884. // stream of execution has access to the address any longer.
  885. CTEAssert (oldvalue > 0);
  886. if (oldvalue == 1)
  887. {
  888. SpxAddrFileDestroy(pAddrFile);
  889. }
  890. }
  891. PSPX_ADDR
  892. SpxAddrLookup(
  893. IN PDEVICE Device,
  894. IN USHORT Socket
  895. )
  896. /*++
  897. Routine Description:
  898. This routine scans the transport addresses defined for the given
  899. device context and compares them with the specified NETWORK
  900. NAME values. If an exact match is found, then a pointer to the
  901. ADDRESS object is returned, and as a side effect, the reference
  902. count to the address object is incremented. If the address is not
  903. found, then NULL is returned.
  904. NOTE: This routine must be called with the Device
  905. spinlock held.
  906. Arguments:
  907. Device - Pointer to the device object and its extension.
  908. Socket - The socket to look up.
  909. Return Value:
  910. Pointer to the ADDRESS object found, or NULL if not found.
  911. --*/
  912. {
  913. PSPX_ADDR Address;
  914. int index = (int)(Socket & NUM_SPXADDR_HASH_MASK);
  915. for (Address = Device->dev_AddrHashTable[index];
  916. Address != NULL;
  917. Address = Address->sa_Next)
  918. {
  919. if ((Address->sa_Flags & SPX_ADDR_CLOSING) != 0)
  920. {
  921. continue;
  922. }
  923. if (Address->sa_Socket == Socket)
  924. {
  925. // We found the match. Bump the reference count on the address, and
  926. // return a pointer to the address object for the caller to use.
  927. SpxAddrLockReference(Address, AREF_LOOKUP);
  928. return Address;
  929. }
  930. }
  931. // The specified address was not found.
  932. return NULL;
  933. }
  934. BOOLEAN
  935. SpxAddrExists(
  936. IN PDEVICE Device,
  937. IN USHORT Socket
  938. )
  939. /*++
  940. Routine Description:
  941. NOTE: This routine must be called with the Device
  942. spinlock held.
  943. Arguments:
  944. Device - Pointer to the device object and its extension.
  945. Socket - The socket to look up.
  946. Return Value:
  947. TRUE if so, else FALSE
  948. --*/
  949. {
  950. PSPX_ADDR Address;
  951. int index = (int)(Socket & NUM_SPXADDR_HASH_MASK);
  952. for (Address = Device->dev_AddrHashTable[index];
  953. Address != NULL;
  954. Address = Address->sa_Next)
  955. {
  956. if ((Address->sa_Flags & SPX_ADDR_CLOSING) != 0)
  957. {
  958. continue;
  959. }
  960. if (Address->sa_Socket == Socket)
  961. {
  962. // We found the match
  963. return TRUE;
  964. }
  965. }
  966. // The specified address was not found.
  967. return FALSE;
  968. } // SpxAddrExists
  969. NTSTATUS
  970. SpxAddrConnByRemoteIdAddrLock(
  971. IN PSPX_ADDR pSpxAddr,
  972. IN USHORT SrcConnId,
  973. IN PBYTE SrcIpxAddr,
  974. OUT PSPX_CONN_FILE *ppSpxConnFile
  975. )
  976. {
  977. PSPX_CONN_FILE pSpxConnFile;
  978. NTSTATUS status = STATUS_INVALID_CONNECTION;
  979. for (pSpxConnFile = pSpxAddr->sa_ActiveConnList;
  980. pSpxConnFile != NULL;
  981. pSpxConnFile = pSpxConnFile->scf_Next)
  982. {
  983. if ((pSpxConnFile->scf_RemConnId == SrcConnId) &&
  984. (*((UNALIGNED ULONG *)SrcIpxAddr) ==
  985. *((UNALIGNED ULONG *)pSpxConnFile->scf_RemAddr)) &&
  986. (*(UNALIGNED ULONG *)(SrcIpxAddr+4) ==
  987. *(UNALIGNED ULONG *)(pSpxConnFile->scf_RemAddr+4)) &&
  988. (*(UNALIGNED ULONG *)(SrcIpxAddr+8) ==
  989. *(UNALIGNED ULONG *)(pSpxConnFile->scf_RemAddr+8)))
  990. {
  991. SpxConnFileReference(pSpxConnFile, CFREF_ADDR);
  992. *ppSpxConnFile = pSpxConnFile;
  993. status = STATUS_SUCCESS;
  994. break;
  995. }
  996. }
  997. return(status);
  998. }
  999. NTSTATUS
  1000. SpxAddrFileStop(
  1001. IN PSPX_ADDR_FILE pAddrFile,
  1002. IN PSPX_ADDR Address
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine is called to terminate all activity on an pAddrFile and
  1007. destroy the object. We remove every connection and datagram associated
  1008. with this addressfile from the address database and terminate their
  1009. activity. Then, if there are no other outstanding addressfiles open on
  1010. this address, the address will go away.
  1011. Arguments:
  1012. pAddrFile - pointer to the addressFile to be stopped
  1013. Address - the owning address for this addressFile (we do not depend upon
  1014. the pointer in the addressFile because we want this routine to be safe)
  1015. Return Value:
  1016. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the request
  1017. is not for a real address.
  1018. --*/
  1019. {
  1020. PSPX_CONN_FILE pSpxConnFile, pSpxConnFileNext;
  1021. CTELockHandle LockHandle;
  1022. DBGPRINT(ADDRESS, DBG,
  1023. ("SpxAddrFileStop: %lx\n", pAddrFile));
  1024. CTEGetLock (&Address->sa_Lock, &LockHandle);
  1025. if (pAddrFile->saf_Flags & SPX_ADDRFILE_CLOSING)
  1026. {
  1027. CTEFreeLock (&Address->sa_Lock, LockHandle);
  1028. return STATUS_SUCCESS;
  1029. }
  1030. pAddrFile->saf_Flags |= SPX_ADDRFILE_CLOSING;
  1031. pSpxConnFileNext = NULL;
  1032. if (pSpxConnFile = pAddrFile->saf_AssocConnList)
  1033. {
  1034. pSpxConnFileNext = pSpxConnFile;
  1035. SpxConnFileReference(pSpxConnFile, CFREF_ADDR);
  1036. }
  1037. while (pSpxConnFile)
  1038. {
  1039. if (pSpxConnFileNext = pSpxConnFile->scf_AssocNext)
  1040. {
  1041. SpxConnFileReference(pSpxConnFileNext, CFREF_ADDR);
  1042. }
  1043. CTEFreeLock (&Address->sa_Lock, LockHandle);
  1044. DBGPRINT(CREATE, INFO,
  1045. ("SpxAddrFileClose: Assoc conn stop %lx when %lx\n",
  1046. pSpxConnFile, pSpxConnFile->scf_RefCount));
  1047. SpxConnStop(pSpxConnFile);
  1048. SpxConnFileDereference(pSpxConnFile, CFREF_ADDR);
  1049. CTEGetLock (&Address->sa_Lock, &LockHandle);
  1050. pSpxConnFile = pSpxConnFileNext;
  1051. }
  1052. CTEFreeLock (&Address->sa_Lock, LockHandle);
  1053. return STATUS_SUCCESS;
  1054. }
  1055. NTSTATUS
  1056. SpxAddrFileCleanup(
  1057. IN PDEVICE Device,
  1058. IN PREQUEST Request
  1059. )
  1060. /*++
  1061. Routine Description:
  1062. Arguments:
  1063. Request - the close request.
  1064. Return Value:
  1065. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the
  1066. request does not point to a real address.
  1067. --*/
  1068. {
  1069. PSPX_ADDR Address;
  1070. PSPX_ADDR_FILE pSpxAddrFile;
  1071. NTSTATUS status;
  1072. pSpxAddrFile = (PSPX_ADDR_FILE)REQUEST_OPEN_CONTEXT(Request);
  1073. DBGPRINT(ADDRESS, INFO,
  1074. ("SpxAddrFileCleanup: %lx\n", pSpxAddrFile));
  1075. status = SpxAddrFileVerify(pSpxAddrFile);
  1076. if (!NT_SUCCESS (status))
  1077. {
  1078. return(status);
  1079. }
  1080. // We assume that addressFile has already been verified
  1081. // at this point.
  1082. Address = pSpxAddrFile->saf_Addr;
  1083. CTEAssert (Address);
  1084. SpxAddrFileStop(pSpxAddrFile, Address);
  1085. SpxAddrFileDereference(pSpxAddrFile, AFREF_VERIFY);
  1086. return STATUS_SUCCESS;
  1087. }
  1088. NTSTATUS
  1089. SpxAddrFileClose(
  1090. IN PDEVICE Device,
  1091. IN PREQUEST Request
  1092. )
  1093. /*++
  1094. Routine Description:
  1095. This routine is called to close the addressfile pointed to by a file
  1096. object. If there is any activity to be run down, we will run it down
  1097. before we terminate the addressfile. We remove every connection and
  1098. datagram associated with this addressfile from the address database
  1099. and terminate their activity. Then, if there are no other outstanding
  1100. addressfiles open on this address, the address will go away.
  1101. Arguments:
  1102. Request - the close request.
  1103. Return Value:
  1104. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the
  1105. request does not point to a real address.
  1106. --*/
  1107. {
  1108. PSPX_ADDR Address;
  1109. PSPX_ADDR_FILE pSpxAddrFile;
  1110. NTSTATUS status;
  1111. pSpxAddrFile = (PSPX_ADDR_FILE)REQUEST_OPEN_CONTEXT(Request);
  1112. DBGPRINT(ADDRESS, DBG,
  1113. ("SpxAddrFileClose: %lx\n", pSpxAddrFile));
  1114. status = SpxAddrFileVerify(pSpxAddrFile);
  1115. if (!NT_SUCCESS (status))
  1116. {
  1117. return(status);
  1118. }
  1119. pSpxAddrFile->saf_CloseReq = Request;
  1120. // We assume that addressFile has already been verified
  1121. // at this point.
  1122. Address = pSpxAddrFile->saf_Addr;
  1123. CTEAssert (Address);
  1124. // Remove us from the access info for this address.
  1125. KeEnterCriticalRegion();
  1126. ExAcquireResourceExclusiveLite (&Device->dev_AddrResource, TRUE);
  1127. #ifdef ISN_NT
  1128. IoRemoveShareAccess (pSpxAddrFile->saf_FileObject, &Address->u.sa_ShareAccess);
  1129. #endif
  1130. ExReleaseResourceLite (&Device->dev_AddrResource);
  1131. KeLeaveCriticalRegion();
  1132. SpxAddrFileDereference (pSpxAddrFile, AFREF_CREATE);
  1133. SpxAddrFileDereference(pSpxAddrFile, AFREF_VERIFY);
  1134. return STATUS_PENDING;
  1135. } // SpxCloseAddressFile
  1136. USHORT
  1137. SpxAddrAssignSocket(
  1138. IN PDEVICE Device
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. This routine assigns a socket that is unique within a range
  1143. of SocketUniqueness.
  1144. Arguments:
  1145. Device - Pointer to the device context.
  1146. Return Value:
  1147. The assigned socket number, or 0 if a unique one cannot
  1148. be found.
  1149. --*/
  1150. {
  1151. BOOLEAN wrapped = FALSE;
  1152. USHORT temp, Socket;
  1153. // We have to auto-assign a socket.
  1154. temp = Device->dev_CurrentSocket;
  1155. PUTSHORT2SHORT(
  1156. &Socket,
  1157. Device->dev_CurrentSocket);
  1158. while (TRUE)
  1159. {
  1160. Device->dev_CurrentSocket += (USHORT)PARAM(CONFIG_SOCKET_UNIQUENESS);
  1161. if (Device->dev_CurrentSocket > PARAM(CONFIG_SOCKET_RANGE_END))
  1162. {
  1163. Device->dev_CurrentSocket = (USHORT)PARAM(CONFIG_SOCKET_RANGE_START);
  1164. wrapped = TRUE;
  1165. }
  1166. if (!SpxAddrExists (Device, Socket))
  1167. {
  1168. break;
  1169. }
  1170. PUTSHORT2SHORT(
  1171. &Socket,
  1172. Device->dev_CurrentSocket);
  1173. if (wrapped && (Device->dev_CurrentSocket >= temp))
  1174. {
  1175. // If we have checked all possible values given SOCKET_UNIQUENESS...
  1176. // This may actually return ERROR even if there are
  1177. // available socket numbers although they may be
  1178. // implicitly in use due to SOCKET_UNIQUENESS being
  1179. // > 1. That is the way it is to work.
  1180. Socket = 0;
  1181. break;
  1182. }
  1183. }
  1184. DBGPRINT(ADDRESS, INFO,
  1185. ("OpenAddress, assigned socket %lx\n", Socket));
  1186. return(Socket);
  1187. }
  1188. VOID
  1189. spxAddrInsertIntoGlobalList(
  1190. IN PSPX_ADDR_FILE pSpxAddrFile
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. Arguments:
  1195. Return Value:
  1196. --*/
  1197. {
  1198. CTELockHandle lockHandle;
  1199. // Get the global q lock
  1200. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  1201. pSpxAddrFile->saf_GlobalNext = SpxGlobalAddrList;
  1202. SpxGlobalAddrList = pSpxAddrFile;
  1203. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  1204. return;
  1205. }
  1206. NTSTATUS
  1207. spxAddrRemoveFromGlobalList(
  1208. IN PSPX_ADDR_FILE pSpxAddrFile
  1209. )
  1210. /*++
  1211. Routine Description:
  1212. Arguments:
  1213. Return Value:
  1214. --*/
  1215. {
  1216. CTELockHandle lockHandle;
  1217. PSPX_ADDR_FILE pC, *ppC;
  1218. NTSTATUS status = STATUS_SUCCESS;
  1219. // Get the global q lock
  1220. CTEGetLock(&SpxGlobalQInterlock, &lockHandle);
  1221. for (ppC = &SpxGlobalAddrList;
  1222. (pC = *ppC) != NULL;)
  1223. {
  1224. if (pC == pSpxAddrFile)
  1225. {
  1226. DBGPRINT(SEND, INFO,
  1227. ("SpxAddrRemoveFromGlobal: %lx\n", pSpxAddrFile));
  1228. // Remove from list
  1229. *ppC = pC->saf_GlobalNext;
  1230. break;
  1231. }
  1232. ppC = &pC->saf_GlobalNext;
  1233. }
  1234. CTEFreeLock(&SpxGlobalQInterlock, lockHandle);
  1235. if (pC == NULL)
  1236. status = STATUS_INVALID_ADDRESS;
  1237. return(status);
  1238. }