Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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