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.

2395 lines
65 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. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // Map all generic accesses to the same one.
  17. //
  18. static GENERIC_MAPPING AddressGenericMapping =
  19. { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  20. TDI_ADDRESS_NETBIOS *
  21. NbiParseTdiAddress(
  22. IN TRANSPORT_ADDRESS UNALIGNED *TransportAddress,
  23. IN ULONG MaxBufferLength,
  24. IN BOOLEAN BroadcastAddressOk
  25. )
  26. /*++
  27. Routine Description:
  28. This routine scans a TRANSPORT_ADDRESS, looking for an address
  29. of type TDI_ADDRESS_TYPE_NETBIOS.
  30. Arguments:
  31. Transport - The generic TDI address.
  32. BroadcastAddressOk - TRUE if we should return the broadcast
  33. address if found. If so, a value of (PVOID)-1 indicates
  34. the broadcast address.
  35. Return Value:
  36. A pointer to the Netbios address, or NULL if none is found,
  37. or (PVOID)-1 if the broadcast address is found.
  38. --*/
  39. {
  40. TA_ADDRESS * addressName;
  41. INT i;
  42. ULONG LastBufferLength;
  43. //
  44. // At least 1 Netbios address should be present
  45. //
  46. if (MaxBufferLength < sizeof(TA_NETBIOS_ADDRESS))
  47. {
  48. return NULL;
  49. }
  50. addressName = &TransportAddress->Address[0];
  51. //
  52. // The name can be passed with multiple entries; we'll take and use only
  53. // the Netbios one.
  54. //
  55. LastBufferLength = FIELD_OFFSET(TRANSPORT_ADDRESS,Address); // Just before Address[0]
  56. for (i=0;i<TransportAddress->TAAddressCount;i++)
  57. {
  58. if (addressName->AddressType == TDI_ADDRESS_TYPE_NETBIOS)
  59. {
  60. if ((addressName->AddressLength == 0) && BroadcastAddressOk)
  61. {
  62. return (PVOID)-1;
  63. }
  64. else if (addressName->AddressLength == sizeof(TDI_ADDRESS_NETBIOS))
  65. {
  66. return ((TDI_ADDRESS_NETBIOS *)(addressName->Address));
  67. }
  68. }
  69. //
  70. // Update LastBufferLength + check for space for at least one
  71. // Netbios address beyond this
  72. //
  73. LastBufferLength += FIELD_OFFSET(TA_ADDRESS,Address) + addressName->AddressLength;
  74. if (MaxBufferLength < (LastBufferLength +
  75. (sizeof(TA_NETBIOS_ADDRESS)-FIELD_OFFSET(TRANSPORT_ADDRESS,Address))))
  76. {
  77. NbiPrint0 ("NbiParseTdiAddress: No valid Netbios address to register!\n");
  78. return (NULL);
  79. }
  80. addressName = (TA_ADDRESS *)(addressName->Address + addressName->AddressLength);
  81. }
  82. return NULL;
  83. } /* NbiParseTdiAddress */
  84. BOOLEAN
  85. NbiValidateTdiAddress(
  86. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
  87. IN ULONG TransportAddressLength
  88. )
  89. /*++
  90. Routine Description:
  91. This routine scans a TRANSPORT_ADDRESS, verifying that the
  92. components of the address do not extend past the specified
  93. length.
  94. Arguments:
  95. TransportAddress - The generic TDI address.
  96. TransportAddressLength - The specific length of TransportAddress.
  97. Return Value:
  98. TRUE if the address is valid, FALSE otherwise.
  99. --*/
  100. {
  101. PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
  102. TA_ADDRESS * addressName;
  103. INT i;
  104. if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount)) {
  105. NbiPrint0 ("NbfValidateTdiAddress: runt address\n");
  106. return FALSE;
  107. }
  108. addressName = &TransportAddress->Address[0];
  109. for (i=0;i<TransportAddress->TAAddressCount;i++) {
  110. if (addressName->Address > AddressEnd) {
  111. NbiPrint0 ("NbiValidateTdiAddress: address too short\n");
  112. return FALSE;
  113. }
  114. addressName = (TA_ADDRESS *)(addressName->Address +
  115. addressName->AddressLength);
  116. }
  117. if ((PUCHAR)addressName > AddressEnd) {
  118. NbiPrint0 ("NbiValidateTdiAddress: address too short\n");
  119. return FALSE;
  120. }
  121. return TRUE;
  122. } /* NbiValidateTdiAddress */
  123. NTSTATUS
  124. NbiOpenAddress(
  125. IN PDEVICE Device,
  126. IN PREQUEST Request
  127. )
  128. /*++
  129. Routine Description:
  130. This routine opens a file that points to an existing address object, or, if
  131. the object doesn't exist, creates it (note that creation of the address
  132. object includes registering the address, and may take many seconds to
  133. complete, depending upon system configuration).
  134. If the address already exists, and it has an ACL associated with it, the
  135. ACL is checked for access rights before allowing creation of the address.
  136. Arguments:
  137. Device - pointer to the device describing the Netbios transport.
  138. Request - a pointer to the request used for the creation of the address.
  139. Return Value:
  140. NTSTATUS - status of operation.
  141. --*/
  142. {
  143. NTSTATUS status;
  144. PADDRESS Address;
  145. PADDRESS_FILE AddressFile;
  146. PFILE_FULL_EA_INFORMATION ea;
  147. TRANSPORT_ADDRESS UNALIGNED *name;
  148. TDI_ADDRESS_NETBIOS * NetbiosAddress;
  149. ULONG DesiredShareAccess;
  150. CTELockHandle LockHandle;
  151. PACCESS_STATE AccessState;
  152. ACCESS_MASK GrantedAccess;
  153. BOOLEAN AccessAllowed;
  154. BOOLEAN found = FALSE;
  155. ULONG AddressLength = 0;
  156. #ifdef ISN_NT
  157. PIRP Irp = (PIRP)Request;
  158. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  159. #endif
  160. #if 0
  161. TA_NETBIOS_ADDRESS FakeAddress;
  162. #endif
  163. //
  164. // The network name is in the EA, passed in the request.
  165. //
  166. ea = OPEN_REQUEST_EA_INFORMATION(Request);
  167. if (ea == NULL) {
  168. NbiPrint1("OpenAddress: REQUEST %lx has no EA\n", Request);
  169. return STATUS_INVALID_ADDRESS_COMPONENT;
  170. }
  171. //
  172. // this may be a valid name; parse the name from the EA and use it if OK.
  173. //
  174. name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
  175. AddressLength = (ULONG) ea->EaValueLength;
  176. #if 0
  177. TdiBuildNetbiosAddress(
  178. "ADAMBA67 ",
  179. FALSE,
  180. &FakeAddress);
  181. name = (PTRANSPORT_ADDRESS)&FakeAddress;
  182. #endif
  183. //
  184. // The name can be passed with multiple entries; we'll take and use only
  185. // the first one of type Netbios. This call returns (PVOID)-1 if the
  186. // address is the broadcast address.
  187. //
  188. NetbiosAddress = NbiParseTdiAddress (name, AddressLength, TRUE);
  189. if (NetbiosAddress == NULL) {
  190. NbiPrint1("OpenAddress: REQUEST %lx has no Netbios Address\n", Request);
  191. return STATUS_INVALID_ADDRESS_COMPONENT;
  192. }
  193. //
  194. // get an address file structure to represent this address.
  195. //
  196. AddressFile = NbiCreateAddressFile (Device);
  197. if (AddressFile == (PADDRESS_FILE)NULL) {
  198. return STATUS_INSUFFICIENT_RESOURCES;
  199. }
  200. //
  201. // See if this address is already established. This call automatically
  202. // increments the reference count on the address so that it won't disappear
  203. // from underneath us after this call but before we have a chance to use it.
  204. //
  205. // To ensure that we don't create two address objects for the
  206. // same address, we hold the device context addressResource until
  207. // we have found the address or created a new one.
  208. //
  209. KeEnterCriticalRegion();
  210. ExAcquireResourceExclusiveLite (&Device->AddressResource, TRUE);
  211. Address = NbiFindAddress(Device, (NetbiosAddress == (PVOID)-1 ) ? (PVOID)-1:NetbiosAddress->NetbiosName);
  212. if (Address == NULL) {
  213. //
  214. // This address doesn't exist. Create it.
  215. // This initializes the address with a ref
  216. // of type ADDRESS_FILE, so if we fail here
  217. // we need to remove that.
  218. //
  219. if (NT_SUCCESS (status = NbiCreateAddress (Request, AddressFile, IrpSp, Device, NetbiosAddress, &Address))) {
  220. ExReleaseResourceLite (&Device->AddressResource);
  221. KeLeaveCriticalRegion();
  222. ASSERT (Address);
  223. if (status == STATUS_PENDING) {
  224. NbiStartRegistration (Address);
  225. }
  226. NbiDereferenceAddress (Address, AREF_ADDRESS_FILE); // We had 1 extra ref in NbiCreateAddress
  227. } else {
  228. ExReleaseResourceLite (&Device->AddressResource);
  229. KeLeaveCriticalRegion();
  230. //
  231. // If the address could not be created, and is not in the
  232. // process of being created, then we can't open up an address.
  233. // Since we can't use the AddressLock to deref, we just destroy
  234. // the address file.
  235. //
  236. NbiDestroyAddressFile (AddressFile);
  237. status = STATUS_INSUFFICIENT_RESOURCES;
  238. }
  239. } else {
  240. NB_DEBUG2 (ADDRESS, ("Add to address %lx\n", Address));
  241. //
  242. // Set this now in case we have to deref.
  243. //
  244. AddressFile->AddressLock = &Address->Lock;
  245. //
  246. // Make sure the types do not conflict.
  247. //
  248. if ((NetbiosAddress != (PVOID)-1) &&
  249. (NetbiosAddress->NetbiosNameType != Address->NetbiosAddress.NetbiosNameType)) {
  250. NB_DEBUG (ADDRESS, ("Address types conflict %lx\n", Address));
  251. ExReleaseResourceLite (&Device->AddressResource);
  252. KeLeaveCriticalRegion();
  253. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  254. status = STATUS_DUPLICATE_NAME;
  255. } else {
  256. //
  257. // The address already exists. Check the ACL and see if we
  258. // can access it. If so, simply use this address as our address.
  259. //
  260. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  261. AccessAllowed = SeAccessCheck(
  262. Address->SecurityDescriptor,
  263. &AccessState->SubjectSecurityContext,
  264. FALSE, // tokens locked
  265. IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
  266. (ACCESS_MASK)0, // previously granted
  267. NULL, // privileges
  268. &AddressGenericMapping,
  269. (KPROCESSOR_MODE)((IrpSp->Flags&SL_FORCE_ACCESS_CHECK) ? UserMode : Irp->RequestorMode),
  270. &GrantedAccess,
  271. &status);
  272. if (!AccessAllowed) {
  273. NB_DEBUG (ADDRESS, ("Address access not allowed %lx\n", Address));
  274. ExReleaseResourceLite (&Device->AddressResource);
  275. KeLeaveCriticalRegion();
  276. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  277. } else {
  278. //
  279. // Now check that we can obtain the desired share
  280. // access. We use read access to control all access.
  281. //
  282. DesiredShareAccess = (ULONG)
  283. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  284. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  285. FILE_SHARE_READ : 0);
  286. status = IoCheckShareAccess(
  287. FILE_READ_DATA,
  288. DesiredShareAccess,
  289. IrpSp->FileObject,
  290. &Address->u.ShareAccess,
  291. TRUE);
  292. if (!NT_SUCCESS (status)) {
  293. NB_DEBUG (ADDRESS, ("Address share access wrong %lx\n", Address));
  294. ExReleaseResourceLite (&Device->AddressResource);
  295. KeLeaveCriticalRegion();
  296. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  297. } else {
  298. ExReleaseResourceLite (&Device->AddressResource);
  299. KeLeaveCriticalRegion();
  300. NB_GET_LOCK (&Address->Lock, &LockHandle);
  301. //
  302. // Insert the address file on the address
  303. // list; we will pend this open if the address
  304. // is still registering. If the address has
  305. // already failed as duplicate, then we
  306. // fail the open.
  307. //
  308. if (Address->Flags & ADDRESS_FLAGS_DUPLICATE_NAME) {
  309. NB_DEBUG (ADDRESS, ("Address duplicated %lx\n", Address));
  310. NB_FREE_LOCK (&Address->Lock, LockHandle);
  311. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  312. status = STATUS_DUPLICATE_NAME;
  313. } else {
  314. InsertTailList (
  315. &Address->AddressFileDatabase,
  316. &AddressFile->Linkage);
  317. //
  318. // Start registration unless it is registered or
  319. // it is the broadcast address.
  320. //
  321. if ((Address->State == ADDRESS_STATE_REGISTERING) &&
  322. (NetbiosAddress != (PVOID)-1)) {
  323. AddressFile->OpenRequest = Request;
  324. AddressFile->State = ADDRESSFILE_STATE_OPENING;
  325. status = STATUS_PENDING;
  326. } else {
  327. AddressFile->OpenRequest = NULL;
  328. AddressFile->State = ADDRESSFILE_STATE_OPEN;
  329. status = STATUS_SUCCESS;
  330. }
  331. AddressFile->Address = Address;
  332. #ifdef ISN_NT
  333. AddressFile->FileObject = IrpSp->FileObject;
  334. #endif
  335. NbiReferenceAddress (Address, AREF_ADDRESS_FILE);
  336. REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
  337. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  338. NB_FREE_LOCK (&Address->Lock, LockHandle);
  339. }
  340. }
  341. }
  342. }
  343. //
  344. // Remove the reference from NbiLookupAddress.
  345. //
  346. NbiDereferenceAddress (Address, AREF_LOOKUP);
  347. }
  348. return status;
  349. } /* NbiOpenAddress */
  350. VOID
  351. NbiStartRegistration(
  352. IN PADDRESS Address
  353. )
  354. /*++
  355. Routine Description:
  356. This routine starts the registration process for a netbios name
  357. by sending out the first add name packet and starting the timer
  358. so that NbiRegistrationTimeout is called after the correct timeout.
  359. Arguments:
  360. Address - The address which is to be registered.
  361. Return Value:
  362. NTSTATUS - status of operation.
  363. --*/
  364. {
  365. NB_DEBUG2 (ADDRESS, ("StartRegistration of %lx\n", Address));
  366. //
  367. // First send out an add name packet.
  368. //
  369. NbiSendNameFrame(
  370. Address,
  371. (UCHAR)(Address->NameTypeFlag | NB_NAME_USED),
  372. NB_CMD_ADD_NAME,
  373. NULL,
  374. NULL);
  375. Address->RegistrationCount = 0;
  376. //
  377. // Now start the timer.
  378. //
  379. NbiReferenceAddress (Address, AREF_TIMER);
  380. CTEInitTimer (&Address->RegistrationTimer);
  381. CTEStartTimer(
  382. &Address->RegistrationTimer,
  383. Address->Device->BroadcastTimeout,
  384. NbiRegistrationTimeout,
  385. (PVOID)Address);
  386. } /* NbiStartRegistration */
  387. VOID
  388. NbiRegistrationTimeout(
  389. IN CTEEvent * Event,
  390. IN PVOID Context
  391. )
  392. /*++
  393. Routine Description:
  394. This routine is called when the address registration
  395. timer expires. It sends another add name if needed, or
  396. checks the result if the correct number have been sent.
  397. Arguments:
  398. Event - The event used to queue the timer.
  399. Context - The context, which is the address pointer.
  400. Return Value:
  401. None.
  402. --*/
  403. {
  404. PADDRESS Address = (PADDRESS)Context;
  405. CTELockHandle LockHandle;
  406. PADDRESS_FILE AddressFile, ReferencedAddressFile;
  407. PLIST_ENTRY p;
  408. ++Address->RegistrationCount;
  409. if ((Address->RegistrationCount < Address->Device->BroadcastCount) &&
  410. ((Address->Flags & ADDRESS_FLAGS_DUPLICATE_NAME) == 0)) {
  411. NB_DEBUG2 (ADDRESS, ("Send add name %d for %lx\n", Address->RegistrationCount+1, Address));
  412. NbiSendNameFrame(
  413. Address,
  414. (UCHAR)(Address->NameTypeFlag | NB_NAME_USED),
  415. NB_CMD_ADD_NAME,
  416. NULL,
  417. NULL);
  418. CTEStartTimer(
  419. &Address->RegistrationTimer,
  420. Address->Device->BroadcastTimeout,
  421. NbiRegistrationTimeout,
  422. (PVOID)Address);
  423. } else {
  424. //
  425. // The correct number of frames have been sent, see what
  426. // happened.
  427. //
  428. NB_DEBUG2 (ADDRESS, ("Done with add names for %lx\n", Address));
  429. ReferencedAddressFile = NULL;
  430. NB_GET_LOCK (&Address->Lock, &LockHandle);
  431. for (p = Address->AddressFileDatabase.Flink;
  432. p != &Address->AddressFileDatabase;
  433. p = p->Flink) {
  434. AddressFile = CONTAINING_RECORD (p, ADDRESS_FILE, Linkage);
  435. CTEAssert (AddressFile->State == ADDRESSFILE_STATE_OPENING);
  436. CTEAssert (AddressFile->OpenRequest != NULL);
  437. NbiReferenceAddressFileLock (AddressFile, AFREF_TIMEOUT);
  438. NB_FREE_LOCK (&Address->Lock, LockHandle);
  439. if (ReferencedAddressFile) {
  440. NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_TIMEOUT);
  441. }
  442. //
  443. // Now see what to do with this address file.
  444. //
  445. REQUEST_INFORMATION(AddressFile->OpenRequest) = 0;
  446. if (Address->Flags & ADDRESS_FLAGS_DUPLICATE_NAME) {
  447. NB_DEBUG (ADDRESS, ("Open of address file %lx failed, duplicate\n", AddressFile));
  448. REQUEST_STATUS(AddressFile->OpenRequest) = STATUS_DUPLICATE_NAME;
  449. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  450. } else {
  451. NB_DEBUG2 (ADDRESS, ("Complete open of address file %lx\n", AddressFile));
  452. REQUEST_STATUS(AddressFile->OpenRequest) = STATUS_SUCCESS;
  453. AddressFile->State = ADDRESSFILE_STATE_OPEN;
  454. }
  455. NbiCompleteRequest (AddressFile->OpenRequest);
  456. NbiFreeRequest (Address->Device, AddressFile->OpenRequest);
  457. NB_GET_LOCK (&Address->Lock, &LockHandle);
  458. ReferencedAddressFile = AddressFile;
  459. }
  460. //
  461. // Set the Address Flag here since in the loop above, we are constantly
  462. // releasing and reacquiring the lock -- hence we could have a new
  463. // client added to this address, but there there would be no OpenRequest
  464. // value since he would think that the registration process had already completed.
  465. //
  466. if ((Address->Flags & ADDRESS_FLAGS_DUPLICATE_NAME) == 0) {
  467. Address->State = ADDRESS_STATE_OPEN;
  468. } else {
  469. Address->State = ADDRESS_STATE_STOPPING;
  470. }
  471. NB_FREE_LOCK (&Address->Lock, LockHandle);
  472. if (ReferencedAddressFile) {
  473. NbiDereferenceAddressFile (ReferencedAddressFile, AFREF_TIMEOUT);
  474. }
  475. NbiDereferenceAddress (Address, AREF_TIMER);
  476. }
  477. } /* NbiRegistrationTimeout */
  478. VOID
  479. NbiProcessFindName(
  480. IN PIPX_LOCAL_TARGET RemoteAddress,
  481. IN ULONG MacOptions,
  482. IN PUCHAR PacketBuffer,
  483. IN UINT PacketSize
  484. )
  485. /*++
  486. Routine Description:
  487. This routine handles NB_CMD_FIND_NAME frames.
  488. Arguments:
  489. RemoteAddress - The local target this packet was received from.
  490. MacOptions - The MAC options for the underlying NDIS binding.
  491. LookaheadBuffer - The packet data, starting at the IPX
  492. header.
  493. PacketSize - The total length of the packet, starting at the
  494. IPX header.
  495. Return Value:
  496. None.
  497. --*/
  498. {
  499. PADDRESS Address;
  500. NB_CONNECTIONLESS UNALIGNED * NbConnectionless =
  501. (NB_CONNECTIONLESS UNALIGNED *)PacketBuffer;
  502. PDEVICE Device = NbiDevice;
  503. if (PacketSize != sizeof(IPX_HEADER) + sizeof(NB_NAME_FRAME)) {
  504. return;
  505. }
  506. //
  507. // Quick check for any names starting with this character.
  508. //
  509. if (Device->AddressCounts[NbConnectionless->NameFrame.Name[0]] == 0) {
  510. return;
  511. }
  512. //
  513. // Always respond to broadcast requests.
  514. //
  515. #if defined(_PNP_POWER)
  516. if (RtlEqualMemory (NetbiosBroadcastName, NbConnectionless->NameFrame.Name, 16)) {
  517. NbiSendNameFrame(
  518. NULL,
  519. NB_NAME_DUPLICATED, // this is what Novell machines use
  520. NB_CMD_NAME_RECOGNIZED,
  521. RemoteAddress,
  522. NbConnectionless);
  523. } else if (Address = NbiFindAddress(Device, (PUCHAR)NbConnectionless->NameFrame.Name)) {
  524. NbiSendNameFrame(
  525. Address,
  526. (UCHAR)(Address->NameTypeFlag | NB_NAME_USED | NB_NAME_REGISTERED),
  527. NB_CMD_NAME_RECOGNIZED,
  528. RemoteAddress,
  529. NbConnectionless);
  530. NbiDereferenceAddress (Address, AREF_FIND);
  531. } else if ( NbiFindAdapterAddress( NbConnectionless->NameFrame.Name, LOCK_NOT_ACQUIRED ) ) {
  532. NbiSendNameFrame(
  533. NULL,
  534. (UCHAR)(NB_NAME_UNIQUE | NB_NAME_USED | NB_NAME_REGISTERED),
  535. NB_CMD_NAME_RECOGNIZED,
  536. RemoteAddress,
  537. NbConnectionless);
  538. }
  539. #else
  540. if (RtlEqualMemory (NetbiosBroadcastName, NbConnectionless->NameFrame.Name, 16)) {
  541. NbiSendNameFrame(
  542. NULL,
  543. NB_NAME_DUPLICATED, // this is what Novell machines use
  544. NB_CMD_NAME_RECOGNIZED,
  545. RemoteAddress,
  546. (PTDI_ADDRESS_IPX)(NbConnectionless->IpxHeader.SourceNetwork));
  547. } else if (Address = NbiFindAddress(Device, (PUCHAR)NbConnectionless->NameFrame.Name)) {
  548. NbiSendNameFrame(
  549. Address,
  550. (UCHAR)(Address->NameTypeFlag | NB_NAME_USED | NB_NAME_REGISTERED),
  551. NB_CMD_NAME_RECOGNIZED,
  552. RemoteAddress,
  553. (PTDI_ADDRESS_IPX)(NbConnectionless->IpxHeader.SourceNetwork));
  554. NbiDereferenceAddress (Address, AREF_FIND);
  555. }
  556. #endif _PNP_POWER
  557. } /* NbiProcessFindName */
  558. VOID
  559. NbiProcessAddName(
  560. IN PIPX_LOCAL_TARGET RemoteAddress,
  561. IN ULONG MacOptions,
  562. IN PUCHAR PacketBuffer,
  563. IN UINT PacketSize
  564. )
  565. /*++
  566. Routine Description:
  567. This routine handles NB_CMD_ADD_NAME frames.
  568. Arguments:
  569. RemoteAddress - The local target this packet was received from.
  570. MacOptions - The MAC options for the underlying NDIS binding.
  571. LookaheadBuffer - The packet data, starting at the IPX
  572. header.
  573. PacketSize - The total length of the packet, starting at the
  574. IPX header.
  575. Return Value:
  576. None.
  577. --*/
  578. {
  579. PADDRESS Address;
  580. NB_CONNECTIONLESS UNALIGNED * NbConnectionless =
  581. (NB_CONNECTIONLESS UNALIGNED *)PacketBuffer;
  582. PDEVICE Device = NbiDevice;
  583. CTELockHandle LockHandle;
  584. BOOLEAN LocalFrame;
  585. if (PacketSize != sizeof(IPX_HEADER) + sizeof(NB_NAME_FRAME)) {
  586. return;
  587. }
  588. //
  589. // Ignore any frame that came from us, except for the purpose
  590. // of updating the cache.
  591. //
  592. if ((Device->Bind.QueryHandler)(
  593. IPX_QUERY_IS_ADDRESS_LOCAL,
  594. #if defined(_PNP_POWER)
  595. &RemoteAddress->NicHandle,
  596. #else
  597. RemoteAddress->NicId,
  598. #endif _PNP_POWER
  599. NbConnectionless->IpxHeader.SourceNetwork,
  600. sizeof(TDI_ADDRESS_IPX),
  601. NULL) == STATUS_SUCCESS) {
  602. LocalFrame = TRUE;
  603. } else {
  604. LocalFrame = FALSE;
  605. }
  606. if (!LocalFrame) {
  607. if ((Device->AddressCounts[NbConnectionless->NameFrame.Name[0]] != 0) &&
  608. (Address = NbiFindAddress(Device, (PUCHAR)NbConnectionless->NameFrame.Name))) {
  609. if (NB_NODE_BROADCAST(NbConnectionless->IpxHeader.DestinationNode)) {
  610. //
  611. // If this frame is an add name (identified because it is a
  612. // broadcast frame) then respond if we have it registered
  613. // unique, or we have it group and someone is trying to add
  614. // it unique.
  615. //
  616. if ((Address->NetbiosAddress.NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_UNIQUE) ||
  617. ((Address->NetbiosAddress.NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP) &&
  618. ((NbConnectionless->NameFrame.NameTypeFlag & NB_NAME_GROUP) == 0))) {
  619. //
  620. // According to GeorgeJ's doc, on a name in use we just
  621. // echo back the name type flags from the request.
  622. //
  623. NbiSendNameFrame(
  624. Address,
  625. NbConnectionless->NameFrame.NameTypeFlag,
  626. NB_CMD_NAME_IN_USE,
  627. RemoteAddress,
  628. #if defined(_PNP_POWER)
  629. NbConnectionless);
  630. #else
  631. (PTDI_ADDRESS_IPX)(NbConnectionless->IpxHeader.SourceNetwork));
  632. #endif _PNP_POWER
  633. }
  634. } else if ((*(UNALIGNED ULONG *)NbConnectionless->IpxHeader.DestinationNetwork ==
  635. *(UNALIGNED ULONG *)Device->Bind.Network) &&
  636. NB_NODE_EQUAL(NbConnectionless->IpxHeader.DestinationNode, Device->Bind.Node)) {
  637. //
  638. // If this is an add name response (which will be sent
  639. // directly to us) then we need to mark the address
  640. // as such.
  641. //
  642. NB_GET_LOCK (&Address->Lock, &LockHandle);
  643. Address->Flags |= ADDRESS_FLAGS_DUPLICATE_NAME;
  644. NB_FREE_LOCK (&Address->Lock, LockHandle);
  645. }
  646. NbiDereferenceAddress (Address, AREF_FIND);
  647. }
  648. }
  649. //
  650. // Pass this frame over to the netbios cache management
  651. // routines to check if they need to update their cache.
  652. //
  653. CacheUpdateFromAddName (RemoteAddress, NbConnectionless, LocalFrame);
  654. } /* NbiProcessAddName */
  655. NTSTATUS
  656. SetAddressSecurityInfo(
  657. IN PADDRESS Address,
  658. IN PIO_STACK_LOCATION IrpSp
  659. )
  660. {
  661. ULONG DesiredShareAccess;
  662. PACCESS_STATE AccessState;
  663. NTSTATUS status;
  664. //
  665. // Initialize the shared access now. We use read access
  666. // to control all access.
  667. //
  668. DesiredShareAccess = (ULONG) (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  669. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  670. FILE_SHARE_READ : 0);
  671. IoSetShareAccess(FILE_READ_DATA, DesiredShareAccess, IrpSp->FileObject, &Address->u.ShareAccess);
  672. //
  673. // Assign the security descriptor (need to do this with
  674. // the spinlock released because the descriptor is not
  675. // mapped).
  676. //
  677. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  678. status = SeAssignSecurity(
  679. NULL, // parent descriptor
  680. AccessState->SecurityDescriptor,
  681. &Address->SecurityDescriptor,
  682. FALSE, // is directory
  683. &AccessState->SubjectSecurityContext,
  684. &AddressGenericMapping,
  685. NonPagedPool);
  686. if (!NT_SUCCESS (status)) {
  687. IoRemoveShareAccess (IrpSp->FileObject, &Address->u.ShareAccess);
  688. }
  689. return status;
  690. }
  691. NTSTATUS
  692. NbiCreateAddress(
  693. IN PREQUEST Request,
  694. IN PADDRESS_FILE AddressFile,
  695. IN PIO_STACK_LOCATION IrpSp,
  696. IN PDEVICE Device,
  697. IN TDI_ADDRESS_NETBIOS *NetbiosAddress,
  698. OUT PADDRESS *pAddress
  699. )
  700. /*++
  701. Routine Description:
  702. This routine creates a transport address and associates it with
  703. the specified transport device context. The reference count in the
  704. address is initialized to 2, and the reference count of the
  705. device context is incremented.
  706. Arguments:
  707. Device - Pointer to the device context (which is really just
  708. the device object with its extension) to be associated with the
  709. address.
  710. NetbiosAddress - The name to assign to this address, or -1 if it
  711. is the broadcast address.
  712. Return Value:
  713. The newly created address, or NULL if none can be allocated.
  714. --*/
  715. {
  716. PADDRESS Address;
  717. CTELockHandle LockHandle;
  718. NTSTATUS status;
  719. //
  720. // if the adapter isn't ready, we can't do any of this; get out
  721. //
  722. if (Device->State != DEVICE_STATE_OPEN) {
  723. return STATUS_DEVICE_NOT_READY;
  724. }
  725. if (!(Address = (PADDRESS)NbiAllocateMemory (sizeof(ADDRESS), MEMORY_ADDRESS, "Address"))) {
  726. NB_DEBUG (ADDRESS, ("Create address %.16s failed\n",
  727. (NetbiosAddress == (PVOID)-1) ? "<broadcast>" : NetbiosAddress->NetbiosName));
  728. return STATUS_INSUFFICIENT_RESOURCES;
  729. }
  730. NB_DEBUG2 (ADDRESS, ("Create address %lx (%.16s)\n", Address,
  731. (NetbiosAddress == (PVOID)-1) ? "<broadcast>" : NetbiosAddress->NetbiosName));
  732. RtlZeroMemory (Address, sizeof(ADDRESS));
  733. if (!NT_SUCCESS (status = SetAddressSecurityInfo(Address, IrpSp))) {
  734. //
  735. // Error, return status.
  736. //
  737. NbiFreeMemory (Address, sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
  738. return status;
  739. }
  740. Address->Type = NB_ADDRESS_SIGNATURE;
  741. Address->Size = sizeof (ADDRESS);
  742. Address->State = ADDRESS_STATE_REGISTERING;
  743. Address->Flags = 0;
  744. Address->Device = Device;
  745. Address->DeviceLock = &Device->Lock;
  746. CTEInitLock (&Address->Lock.Lock);
  747. InitializeListHead (&Address->AddressFileDatabase);
  748. Address->ReferenceCount = 2; // Initialize it to 2 -- it will be Deref'ed by the caller
  749. #if DBG
  750. Address->RefTypes[AREF_ADDRESS_FILE] = 1;
  751. #endif
  752. if (NetbiosAddress == (PVOID)-1) {
  753. Address->NetbiosAddress.Broadcast = TRUE;
  754. } else {
  755. Address->NetbiosAddress.Broadcast = FALSE;
  756. Address->NetbiosAddress.NetbiosNameType = NetbiosAddress->NetbiosNameType;
  757. RtlCopyMemory (Address->NetbiosAddress.NetbiosName, NetbiosAddress->NetbiosName, 16);
  758. ++Device->AddressCounts[NetbiosAddress->NetbiosName[0]];
  759. }
  760. if (Address->NetbiosAddress.NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_UNIQUE) {
  761. Address->NameTypeFlag = NB_NAME_UNIQUE;
  762. } else {
  763. Address->NameTypeFlag = NB_NAME_GROUP;
  764. }
  765. //
  766. // Set this now in case we have to deref.
  767. //
  768. AddressFile->AddressLock = &Address->Lock;
  769. REQUEST_OPEN_CONTEXT(Request) = (PVOID)AddressFile;
  770. REQUEST_OPEN_TYPE(Request) = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  771. AddressFile->FileObject = IrpSp->FileObject;
  772. AddressFile->Address = Address;
  773. NB_INSERT_TAIL_LIST (&Address->AddressFileDatabase, &AddressFile->Linkage, &Address->Lock);
  774. if (NetbiosAddress == (PVOID)-1) {
  775. AddressFile->OpenRequest = NULL;
  776. AddressFile->State = ADDRESSFILE_STATE_OPEN;
  777. status = STATUS_SUCCESS;
  778. } else {
  779. AddressFile->OpenRequest = Request;
  780. AddressFile->State = ADDRESSFILE_STATE_OPENING;
  781. status = STATUS_PENDING;
  782. }
  783. //
  784. // Now link this address into the specified device context's
  785. // address database. To do this, we need to acquire the spin lock
  786. // on the device context.
  787. //
  788. NB_GET_LOCK (&Device->Lock, &LockHandle);
  789. InsertTailList (&Device->AddressDatabase, &Address->Linkage);
  790. ++Device->AddressCount;
  791. NB_FREE_LOCK (&Device->Lock, LockHandle);
  792. NbiReferenceDevice (Device, DREF_ADDRESS);
  793. *pAddress = Address;
  794. return status;
  795. } /* NbiCreateAddress */
  796. NTSTATUS
  797. NbiVerifyAddressFile (
  798. #if defined(_PNP_POWER)
  799. IN PADDRESS_FILE AddressFile,
  800. IN BOOLEAN ConflictIsOk
  801. #else
  802. IN PADDRESS_FILE AddressFile
  803. #endif _PNP_POWER
  804. )
  805. /*++
  806. Routine Description:
  807. This routine is called to verify that the pointer given us in a file
  808. object is in fact a valid address file object. We also verify that the
  809. address object pointed to by it is a valid address object, and reference
  810. it to keep it from disappearing while we use it.
  811. Arguments:
  812. AddressFile - potential pointer to a ADDRESS_FILE object
  813. ConflictIsOk - TRUE if we should succeed the verify even if the
  814. corresponding address is in CONFLICT. ( For Close and
  815. cleanup we return STATUS_SUCCESS even if we are in conflict
  816. so that the addressfile can be destroyed)
  817. Return Value:
  818. STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
  819. --*/
  820. {
  821. CTELockHandle LockHandle;
  822. NTSTATUS status = STATUS_SUCCESS;
  823. PADDRESS Address;
  824. BOOLEAN LockHeld = FALSE;
  825. //
  826. // try to verify the address file signature. If the signature is valid,
  827. // verify the address pointed to by it and get the address spinlock.
  828. // check the address's state, and increment the reference count if it's
  829. // ok to use it. Note that the only time we return an error for state is
  830. // if the address is closing.
  831. //
  832. try {
  833. if ((AddressFile->Size == sizeof (ADDRESS_FILE)) &&
  834. (AddressFile->Type == NB_ADDRESSFILE_SIGNATURE) ) {
  835. // (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) {
  836. Address = AddressFile->Address;
  837. if ((Address->Size == sizeof (ADDRESS)) &&
  838. (Address->Type == NB_ADDRESS_SIGNATURE) ) {
  839. NB_GET_LOCK (&Address->Lock, &LockHandle);
  840. LockHeld = TRUE;
  841. #if defined(_PNP_POWER)
  842. if (Address->State != ADDRESS_STATE_STOPPING &&
  843. ( ConflictIsOk || ( !(Address->Flags & ADDRESS_FLAGS_CONFLICT) )) ) {
  844. #else
  845. if (Address->State != ADDRESS_STATE_STOPPING) {
  846. #endif _PNP_POWER
  847. NbiReferenceAddressFileLock (AddressFile, AFREF_VERIFY);
  848. } else {
  849. NbiPrint1("NbiVerifyAddressFile: A %lx closing\n", Address);
  850. status = STATUS_INVALID_ADDRESS;
  851. }
  852. NB_FREE_LOCK (&Address->Lock, LockHandle);
  853. } else {
  854. NbiPrint1("NbiVerifyAddressFile: A %lx bad signature\n", Address);
  855. status = STATUS_INVALID_ADDRESS;
  856. }
  857. } else {
  858. NbiPrint1("NbiVerifyAddressFile: AF %lx bad signature\n", AddressFile);
  859. status = STATUS_INVALID_ADDRESS;
  860. }
  861. } except(EXCEPTION_EXECUTE_HANDLER) {
  862. NbiPrint1("NbiVerifyAddressFile: AF %lx exception\n", Address);
  863. if (LockHeld) {
  864. NB_FREE_LOCK (&Address->Lock, LockHandle);
  865. }
  866. return GetExceptionCode();
  867. }
  868. return status;
  869. } /* NbiVerifyAddressFile */
  870. VOID
  871. NbiDestroyAddress(
  872. IN PVOID Parameter
  873. )
  874. /*++
  875. Routine Description:
  876. This routine destroys a transport address and removes all references
  877. made by it to other objects in the transport. The address structure
  878. is returned to nonpaged system pool. It is assumed
  879. that the caller has already removed all addressfile structures associated
  880. with this address.
  881. It is called from a worker thread queue by NbiDerefAddress when
  882. the reference count goes to 0.
  883. This thread is only queued by NbiDerefAddress. The reason for
  884. this is that there may be multiple streams of execution which are
  885. simultaneously referencing the same address object, and it should
  886. not be deleted out from under an interested stream of execution.
  887. Arguments:
  888. Address - Pointer to a transport address structure to be destroyed.
  889. Return Value:
  890. NTSTATUS - status of operation.
  891. --*/
  892. {
  893. PADDRESS Address = (PADDRESS)Parameter;
  894. PDEVICE Device = Address->Device;
  895. CTELockHandle LockHandle;
  896. NB_DEBUG2 (ADDRESS, ("Destroy address %lx <%.16s>\n", Address,
  897. Address->NetbiosAddress.Broadcast ? "<broadcast>" : Address->NetbiosAddress.NetbiosName));
  898. SeDeassignSecurity (&Address->SecurityDescriptor);
  899. //
  900. // Delink this address from its associated device context's address
  901. // database. To do this we must spin lock on the device context object,
  902. // not on the address.
  903. //
  904. NB_GET_LOCK (&Device->Lock, &LockHandle);
  905. if (!Address->NetbiosAddress.Broadcast) {
  906. --Device->AddressCounts[Address->NetbiosAddress.NetbiosName[0]];
  907. }
  908. --Device->AddressCount;
  909. RemoveEntryList (&Address->Linkage);
  910. NB_FREE_LOCK (&Device->Lock, LockHandle);
  911. NbiFreeMemory (Address, sizeof(ADDRESS), MEMORY_ADDRESS, "Address");
  912. NbiDereferenceDevice (Device, DREF_ADDRESS);
  913. } /* NbiDestroyAddress */
  914. #if DBG
  915. VOID
  916. NbiRefAddress(
  917. IN PADDRESS Address
  918. )
  919. /*++
  920. Routine Description:
  921. This routine increments the reference count on a transport address.
  922. Arguments:
  923. Address - Pointer to a transport address object.
  924. Return Value:
  925. none.
  926. --*/
  927. {
  928. CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
  929. InterlockedIncrement( &Address->ReferenceCount );
  930. } /* NbiRefAddress */
  931. VOID
  932. NbiRefAddressLock(
  933. IN PADDRESS Address
  934. )
  935. /*++
  936. Routine Description:
  937. This routine increments the reference count on a transport address
  938. when the device lock is already held.
  939. Arguments:
  940. Address - Pointer to a transport address object.
  941. Return Value:
  942. none.
  943. --*/
  944. {
  945. CTEAssert (Address->ReferenceCount > 0); // not perfect, but...
  946. InterlockedIncrement( &Address->ReferenceCount );
  947. } /* NbiRefAddressLock */
  948. #endif
  949. VOID
  950. NbiDerefAddress(
  951. IN PADDRESS Address
  952. )
  953. /*++
  954. Routine Description:
  955. This routine dereferences a transport address by decrementing the
  956. reference count contained in the structure. If, after being
  957. decremented, the reference count is zero, then this routine calls
  958. NbiDestroyAddress to remove it from the system.
  959. Arguments:
  960. Address - Pointer to a transport address object.
  961. Return Value:
  962. none.
  963. --*/
  964. {
  965. ULONG newvalue;
  966. newvalue = InterlockedDecrement( &Address->ReferenceCount );
  967. //
  968. // If we have deleted all references to this address, then we can
  969. // destroy the object. It is okay to have already released the spin
  970. // lock at this point because there is no possible way that another
  971. // stream of execution has access to the address any longer.
  972. //
  973. CTEAssert ((LONG)newvalue >= 0);
  974. if (newvalue == 0) {
  975. #if ISN_NT
  976. ExInitializeWorkItem(
  977. &Address->u.DestroyAddressQueueItem,
  978. NbiDestroyAddress,
  979. (PVOID)Address);
  980. ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
  981. #else
  982. NbiDestroyAddress(Address);
  983. #endif
  984. }
  985. } /* NbiDerefAddress */
  986. PADDRESS_FILE
  987. NbiCreateAddressFile(
  988. IN PDEVICE Device
  989. )
  990. /*++
  991. Routine Description:
  992. This routine creates an address file from the pool of ther
  993. specified device context. The reference count in the
  994. address is automatically set to 1.
  995. Arguments:
  996. Device - Pointer to the device context (which is really just
  997. the device object with its extension) to be associated with the
  998. address.
  999. Return Value:
  1000. The allocate address file or NULL.
  1001. --*/
  1002. {
  1003. CTELockHandle LockHandle;
  1004. PADDRESS_FILE AddressFile;
  1005. UINT i;
  1006. NB_GET_LOCK (&Device->Lock, &LockHandle);
  1007. AddressFile = (PADDRESS_FILE)NbiAllocateMemory (sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
  1008. if (AddressFile == NULL) {
  1009. NB_DEBUG (ADDRESS, ("Create address file failed\n"));
  1010. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1011. return NULL;
  1012. }
  1013. NB_DEBUG2 (ADDRESS, ("Create address file %lx\n", AddressFile));
  1014. RtlZeroMemory (AddressFile, sizeof(ADDRESS_FILE));
  1015. AddressFile->Type = NB_ADDRESSFILE_SIGNATURE;
  1016. AddressFile->Size = sizeof (ADDRESS_FILE);
  1017. InitializeListHead (&AddressFile->ReceiveDatagramQueue);
  1018. InitializeListHead (&AddressFile->ConnectionDatabase);
  1019. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1020. AddressFile->Address = NULL;
  1021. #ifdef ISN_NT
  1022. AddressFile->FileObject = NULL;
  1023. #endif
  1024. AddressFile->Device = Device;
  1025. AddressFile->State = ADDRESSFILE_STATE_OPENING;
  1026. AddressFile->ReferenceCount = 1;
  1027. #if DBG
  1028. AddressFile->RefTypes[AFREF_CREATE] = 1;
  1029. #endif
  1030. AddressFile->CloseRequest = (PREQUEST)NULL;
  1031. //
  1032. // Initialize the request handlers.
  1033. //
  1034. for (i = 0; i < 6; i++) {
  1035. AddressFile->RegisteredHandler[i] = FALSE;
  1036. AddressFile->HandlerContexts[i] = NULL;
  1037. AddressFile->Handlers[i] = TdiDefaultHandlers[i];
  1038. }
  1039. CTEAssert (AddressFile->ConnectionHandler == TdiDefaultConnectHandler);
  1040. CTEAssert (AddressFile->DisconnectHandler == TdiDefaultDisconnectHandler);
  1041. CTEAssert (AddressFile->ErrorHandler == TdiDefaultErrorHandler);
  1042. CTEAssert (AddressFile->ReceiveHandler == TdiDefaultReceiveHandler);
  1043. CTEAssert (AddressFile->ReceiveDatagramHandler == TdiDefaultRcvDatagramHandler);
  1044. CTEAssert (AddressFile->ExpeditedDataHandler == TdiDefaultRcvExpeditedHandler);
  1045. return AddressFile;
  1046. } /* NbiCreateAddressFile */
  1047. NTSTATUS
  1048. NbiDestroyAddressFile(
  1049. IN PADDRESS_FILE AddressFile
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. This routine destroys an address file and removes all references
  1054. made by it to other objects in the transport.
  1055. This routine is only called by NbiDereferenceAddressFile. The reason
  1056. for this is that there may be multiple streams of execution which are
  1057. simultaneously referencing the same address file object, and it should
  1058. not be deleted out from under an interested stream of execution.
  1059. Arguments:
  1060. AddressFile Pointer to a transport address file structure to be destroyed.
  1061. Return Value:
  1062. NTSTATUS - status of operation.
  1063. --*/
  1064. {
  1065. CTELockHandle LockHandle, LockHandle1;
  1066. PADDRESS Address;
  1067. PDEVICE Device;
  1068. PREQUEST CloseRequest;
  1069. BOOLEAN StopAddress;
  1070. NB_DEBUG2 (ADDRESS, ("Destroy address file %lx\n", AddressFile));
  1071. Address = AddressFile->Address;
  1072. Device = AddressFile->Device;
  1073. if (Address) {
  1074. //
  1075. // This addressfile was associated with an address.
  1076. //
  1077. NB_GET_LOCK (&Address->Lock, &LockHandle);
  1078. //
  1079. // remove this addressfile from the address list and disassociate it from
  1080. // the file handle.
  1081. //
  1082. RemoveEntryList (&AddressFile->Linkage);
  1083. InitializeListHead (&AddressFile->Linkage);
  1084. if (Address->AddressFileDatabase.Flink == &Address->AddressFileDatabase) {
  1085. //
  1086. // This is the last open of this address, it will close
  1087. // due to normal dereferencing but we have to set the
  1088. // CLOSING flag too to stop further references.
  1089. //
  1090. NB_GET_LOCK (&Device->Lock, &LockHandle1);
  1091. Address->State = ADDRESS_STATE_STOPPING;
  1092. NB_FREE_LOCK (&Device->Lock, LockHandle1);
  1093. StopAddress = TRUE;
  1094. } else {
  1095. StopAddress = FALSE;
  1096. }
  1097. AddressFile->Address = NULL;
  1098. #ifdef ISN_NT
  1099. AddressFile->FileObject->FsContext = NULL;
  1100. AddressFile->FileObject->FsContext2 = NULL;
  1101. #endif
  1102. NB_FREE_LOCK (&Address->Lock, LockHandle);
  1103. //
  1104. // We will already have been removed from the ShareAccess
  1105. // of the owning address.
  1106. //
  1107. if (StopAddress && (!Address->NetbiosAddress.Broadcast)) {
  1108. NbiSendNameFrame(
  1109. Address,
  1110. (UCHAR)(Address->NameTypeFlag |
  1111. NB_NAME_USED | NB_NAME_REGISTERED | NB_NAME_DEREGISTERED),
  1112. NB_CMD_DELETE_NAME,
  1113. NULL,
  1114. NULL);
  1115. }
  1116. //
  1117. // Now dereference the owning address.
  1118. //
  1119. NbiDereferenceAddress (Address, AREF_ADDRESS_FILE);
  1120. }
  1121. //
  1122. // Save this for later completion.
  1123. //
  1124. CloseRequest = AddressFile->CloseRequest;
  1125. //
  1126. // return the addressFile to the pool of address files
  1127. //
  1128. NbiFreeMemory (AddressFile, sizeof(ADDRESS_FILE), MEMORY_ADDRESS, "AddressFile");
  1129. if (CloseRequest != (PREQUEST)NULL) {
  1130. REQUEST_INFORMATION(CloseRequest) = 0;
  1131. REQUEST_STATUS(CloseRequest) = STATUS_SUCCESS;
  1132. NbiCompleteRequest (CloseRequest);
  1133. NbiFreeRequest (Device, CloseRequest);
  1134. }
  1135. return STATUS_SUCCESS;
  1136. } /* NbiDestroyAddressFile */
  1137. #if DBG
  1138. VOID
  1139. NbiRefAddressFile(
  1140. IN PADDRESS_FILE AddressFile
  1141. )
  1142. /*++
  1143. Routine Description:
  1144. This routine increments the reference count on an address file.
  1145. Arguments:
  1146. AddressFile - Pointer to a transport address file object.
  1147. Return Value:
  1148. none.
  1149. --*/
  1150. {
  1151. CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
  1152. InterlockedIncrement( &AddressFile->ReferenceCount );
  1153. } /* NbiRefAddressFile */
  1154. VOID
  1155. NbiRefAddressFileLock(
  1156. IN PADDRESS_FILE AddressFile
  1157. )
  1158. /*++
  1159. Routine Description:
  1160. This routine increments the reference count on an address file.
  1161. IT IS CALLED WITH THE ADDRESS LOCK HELD.
  1162. Arguments:
  1163. AddressFile - Pointer to a transport address file object.
  1164. Return Value:
  1165. none.
  1166. --*/
  1167. {
  1168. CTEAssert (AddressFile->ReferenceCount > 0); // not perfect, but...
  1169. InterlockedIncrement( &AddressFile->ReferenceCount );
  1170. } /* NbiRefAddressFileLock */
  1171. #endif
  1172. VOID
  1173. NbiDerefAddressFile(
  1174. IN PADDRESS_FILE AddressFile
  1175. )
  1176. /*++
  1177. Routine Description:
  1178. This routine dereferences an address file by decrementing the
  1179. reference count contained in the structure. If, after being
  1180. decremented, the reference count is zero, then this routine calls
  1181. NbiDestroyAddressFile to remove it from the system.
  1182. Arguments:
  1183. AddressFile - Pointer to a transport address file object.
  1184. Return Value:
  1185. none.
  1186. --*/
  1187. {
  1188. ULONG newvalue;
  1189. newvalue = InterlockedDecrement( &AddressFile->ReferenceCount );
  1190. //
  1191. // If we have deleted all references to this address file, then we can
  1192. // destroy the object. It is okay to have already released the spin
  1193. // lock at this point because there is no possible way that another
  1194. // stream of execution has access to the address any longer.
  1195. //
  1196. CTEAssert ((LONG)newvalue >= 0);
  1197. if (newvalue == 0) {
  1198. NbiDestroyAddressFile (AddressFile);
  1199. }
  1200. } /* NbiDerefAddressFile */
  1201. #if !defined(_PNP_POWER)
  1202. PADDRESS
  1203. NbiLookupAddress(
  1204. IN PDEVICE Device,
  1205. IN TDI_ADDRESS_NETBIOS UNALIGNED * NetbiosAddress
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This routine scans the transport addresses defined for the given
  1210. device context and compares them with the specified NETWORK
  1211. NAME values. If an exact match is found, then a pointer to the
  1212. ADDRESS object is returned, and as a side effect, the reference
  1213. count to the address object is incremented. If the address is not
  1214. found, then NULL is returned.
  1215. NOTE: This routine must be called with the Device
  1216. spinlock held.
  1217. Arguments:
  1218. Device - Pointer to the device object and its extension.
  1219. NetbiosAddress - The name to look up, or -1 if the broadcast
  1220. address is being searched for.
  1221. Return Value:
  1222. Pointer to the ADDRESS object found, or NULL if not found.
  1223. --*/
  1224. {
  1225. PADDRESS Address;
  1226. PLIST_ENTRY p;
  1227. p = Device->AddressDatabase.Flink;
  1228. for (p = Device->AddressDatabase.Flink;
  1229. p != &Device->AddressDatabase;
  1230. p = p->Flink) {
  1231. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  1232. if (Address->State == ADDRESS_STATE_STOPPING) {
  1233. continue;
  1234. }
  1235. if (Address->NetbiosAddress.Broadcast) {
  1236. //
  1237. // This address is the broadcast one, so no match
  1238. // unless we are looking for that.
  1239. //
  1240. if (NetbiosAddress != (PVOID)-1) {
  1241. continue;
  1242. }
  1243. } else {
  1244. //
  1245. // This address is not the broadcast, so if we are
  1246. // looking for that then no match, else compare the
  1247. // two names.
  1248. //
  1249. if (NetbiosAddress == (PVOID)-1) {
  1250. continue;
  1251. }
  1252. if (!RtlEqualMemory(
  1253. Address->NetbiosAddress.NetbiosName,
  1254. NetbiosAddress->NetbiosName,
  1255. 16)) {
  1256. continue;
  1257. }
  1258. }
  1259. //
  1260. // We found the match. Bump the reference count on the address, and
  1261. // return a pointer to the address object for the caller to use.
  1262. //
  1263. NbiReferenceAddressLock (Address, AREF_LOOKUP);
  1264. return Address;
  1265. } /* for */
  1266. //
  1267. // The specified address was not found.
  1268. //
  1269. return NULL;
  1270. } /* NbiLookupAddress */
  1271. #endif !_PNP_POWER
  1272. PADDRESS
  1273. NbiFindAddress(
  1274. IN PDEVICE Device,
  1275. IN PUCHAR NetbiosName
  1276. )
  1277. /*++
  1278. Routine Description:
  1279. This routine scans the transport addresses defined for the given
  1280. device context and compares them with the specified NetbiosName
  1281. values. If a match is found, the address is referenced and the
  1282. pointer is returned.
  1283. We ignore any addresses which are either STOPPING or are under
  1284. CONFLICT state.
  1285. A name in CONFLICT is dead for all practical purposes
  1286. except Close. This routine is called by various name service,
  1287. datagram and session sevice routines. We hide any names in CONFLICT
  1288. from these routines.
  1289. This routine is also called by NbiTdiOpenAddress().
  1290. A name could have been marked in CONFLICT ages ago(but is not closed
  1291. yet). We must allow another open of the same name as that might
  1292. succeed now.
  1293. Arguments:
  1294. Device - Pointer to the device object and its extension.
  1295. NetbiosName - The name to look up, or -1 for the broadcast name.
  1296. Return Value:
  1297. Pointer to the ADDRESS object found, or NULL if not found.
  1298. --*/
  1299. {
  1300. PADDRESS Address;
  1301. PLIST_ENTRY p;
  1302. CTELockHandle LockHandle;
  1303. NB_GET_LOCK (&Device->Lock, &LockHandle);
  1304. p = Device->AddressDatabase.Flink;
  1305. for (p = Device->AddressDatabase.Flink;
  1306. p != &Device->AddressDatabase;
  1307. p = p->Flink) {
  1308. Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
  1309. #if defined(_PNP_POWER)
  1310. if ( ( Address->State == ADDRESS_STATE_STOPPING ) ||
  1311. ( Address->Flags & ADDRESS_FLAGS_CONFLICT ) ) {
  1312. #else
  1313. if (Address->State == ADDRESS_STATE_STOPPING) {
  1314. #endif _PNP_POWER
  1315. continue;
  1316. }
  1317. if (Address->NetbiosAddress.Broadcast) {
  1318. //
  1319. // This address is the broadcast one, so no match
  1320. // unless we are looking for that.
  1321. //
  1322. if (NetbiosName != (PVOID)-1) {
  1323. continue;
  1324. }
  1325. } else {
  1326. //
  1327. // This address is not the broadcast, so if we are
  1328. // looking for that then no match, else compare the
  1329. // two names.
  1330. //
  1331. if ((NetbiosName == (PVOID)-1) ||
  1332. (!RtlEqualMemory(
  1333. Address->NetbiosAddress.NetbiosName,
  1334. NetbiosName,
  1335. 16))) {
  1336. continue;
  1337. }
  1338. }
  1339. //
  1340. // We found the match. Bump the reference count on the address, and
  1341. // return a pointer to the address object for the caller to use.
  1342. //
  1343. NbiReferenceAddressLock (Address, AREF_FIND);
  1344. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1345. return Address;
  1346. } /* for */
  1347. //
  1348. // The specified address was not found.
  1349. //
  1350. NB_FREE_LOCK (&Device->Lock, LockHandle);
  1351. return NULL;
  1352. } /* NbiFindAddress */
  1353. NTSTATUS
  1354. NbiStopAddressFile(
  1355. IN PADDRESS_FILE AddressFile,
  1356. IN PADDRESS Address
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. This routine is called to terminate all activity on an AddressFile and
  1361. destroy the object. We remove every connection and datagram associated
  1362. with this addressfile from the address database and terminate their
  1363. activity. Then, if there are no other outstanding addressfiles open on
  1364. this address, the address will go away.
  1365. Arguments:
  1366. AddressFile - pointer to the addressFile to be stopped
  1367. Address - the owning address for this addressFile (we do not depend upon
  1368. the pointer in the addressFile because we want this routine to be safe)
  1369. Return Value:
  1370. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the request
  1371. is not for a real address.
  1372. --*/
  1373. {
  1374. PLIST_ENTRY p;
  1375. PCONNECTION Connection;
  1376. PREQUEST Request;
  1377. PDEVICE Device = Address->Device;
  1378. CTELockHandle LockHandle1, LockHandle2;
  1379. LIST_ENTRY SendDatagramList;
  1380. PNB_SEND_RESERVED Reserved;
  1381. PREQUEST DatagramRequest;
  1382. NB_DEFINE_LOCK_HANDLE (LockHandle3)
  1383. CTELockHandle CancelLH;
  1384. NB_DEFINE_SYNC_CONTEXT (SyncContext)
  1385. LIST_ENTRY DatagramQ;
  1386. NB_GET_LOCK (&Address->Lock, &LockHandle1);
  1387. if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) {
  1388. NB_FREE_LOCK (&Address->Lock, LockHandle1);
  1389. return STATUS_SUCCESS;
  1390. }
  1391. //
  1392. // This prevents anybody else from being put on the
  1393. // ConnectionDatabase.
  1394. //
  1395. AddressFile->State = ADDRESSFILE_STATE_CLOSING;
  1396. while (!IsListEmpty (&AddressFile->ConnectionDatabase)) {
  1397. p = RemoveHeadList (&AddressFile->ConnectionDatabase);
  1398. Connection = CONTAINING_RECORD (p, CONNECTION, AddressFileLinkage);
  1399. CTEAssert (Connection->AddressFile == AddressFile);
  1400. Connection->AddressFileLinked = FALSE;
  1401. NB_GET_LOCK (&Device->Lock, &LockHandle2);
  1402. if (Connection->ReferenceCount == 0) {
  1403. //
  1404. // The refcount is already 0, so we can just
  1405. // NULL out this field to complete the disassociate.
  1406. //
  1407. Connection->AddressFile = NULL;
  1408. NB_FREE_LOCK (&Device->Lock, LockHandle2);
  1409. NB_FREE_LOCK (&Address->Lock, LockHandle1);
  1410. NbiDereferenceAddressFile (AddressFile, AFREF_CONNECTION);
  1411. } else {
  1412. //
  1413. // Mark this so we know to disassociate when the
  1414. // count goes to 0, but that there is no specific
  1415. // request pending on it. We also stop the connection
  1416. // to shut it down.
  1417. //
  1418. Connection->DisassociatePending = (PVOID)-1;
  1419. NbiReferenceConnectionLock (Connection, CREF_DISASSOC);
  1420. NB_FREE_LOCK (&Device->Lock, LockHandle2);
  1421. NB_FREE_LOCK (&Address->Lock, LockHandle1);
  1422. NB_BEGIN_SYNC (&SyncContext);
  1423. NB_SYNC_GET_LOCK (&Connection->Lock, &LockHandle3);
  1424. //
  1425. // This call frees the connection lock.
  1426. //
  1427. NbiStopConnection(
  1428. Connection,
  1429. STATUS_INVALID_ADDRESS
  1430. NB_LOCK_HANDLE_ARG (LockHandle3));
  1431. NB_END_SYNC (&SyncContext);
  1432. NbiDereferenceConnection (Connection, CREF_DISASSOC);
  1433. }
  1434. NB_GET_LOCK (&Address->Lock, &LockHandle1);
  1435. }
  1436. NB_FREE_LOCK (&Address->Lock, LockHandle1);
  1437. //
  1438. // Abort all pending send datagrams.
  1439. //
  1440. InitializeListHead (&SendDatagramList);
  1441. NB_GET_LOCK (&Device->Lock, &LockHandle2);
  1442. p = Device->WaitingDatagrams.Flink;
  1443. while (p != &Device->WaitingDatagrams) {
  1444. Reserved = CONTAINING_RECORD (p, NB_SEND_RESERVED, WaitLinkage);
  1445. p = p->Flink;
  1446. if (Reserved->u.SR_DG.AddressFile == AddressFile) {
  1447. RemoveEntryList (&Reserved->WaitLinkage);
  1448. InsertTailList (&SendDatagramList, &Reserved->WaitLinkage);
  1449. }
  1450. }
  1451. NB_FREE_LOCK (&Device->Lock, LockHandle2);
  1452. for (p = SendDatagramList.Flink; p != &SendDatagramList; ) {
  1453. Reserved = CONTAINING_RECORD (p, NB_SEND_RESERVED, WaitLinkage);
  1454. p = p->Flink;
  1455. DatagramRequest = Reserved->u.SR_DG.DatagramRequest;
  1456. NB_DEBUG2 (DATAGRAM, ("Aborting datagram %lx on %lx\n", DatagramRequest, AddressFile));
  1457. REQUEST_STATUS(DatagramRequest) = STATUS_SUCCESS;
  1458. NbiCompleteRequest(DatagramRequest);
  1459. NbiFreeRequest (Device, DatagramRequest);
  1460. NbiDereferenceAddressFile (AddressFile, AFREF_SEND_DGRAM);
  1461. ExInterlockedPushEntrySList(
  1462. &Device->SendPacketList,
  1463. &Reserved->PoolLinkage,
  1464. &NbiGlobalPoolInterlock);
  1465. }
  1466. //
  1467. // Abort all pending receive datagrams.
  1468. //
  1469. InitializeListHead( &DatagramQ );
  1470. NB_GET_CANCEL_LOCK(&CancelLH);
  1471. NB_GET_LOCK (&Address->Lock, &LockHandle1);
  1472. while (!IsListEmpty(&AddressFile->ReceiveDatagramQueue)) {
  1473. p = RemoveHeadList (&AddressFile->ReceiveDatagramQueue);
  1474. Request = LIST_ENTRY_TO_REQUEST (p);
  1475. // Insert it on a private Q, so it can be completed later.
  1476. InsertTailList( &DatagramQ, p);
  1477. REQUEST_INFORMATION(Request) = 0;
  1478. REQUEST_STATUS(Request) = STATUS_NETWORK_NAME_DELETED;
  1479. IoSetCancelRoutine (Request, (PDRIVER_CANCEL)NULL);
  1480. NbiDereferenceAddressFile (AddressFile, AFREF_RCV_DGRAM);
  1481. }
  1482. NB_FREE_LOCK (&Address->Lock, LockHandle1);
  1483. NB_FREE_CANCEL_LOCK(CancelLH);
  1484. for( p = DatagramQ.Flink; p != &DatagramQ; ) {
  1485. Request = LIST_ENTRY_TO_REQUEST ( p );
  1486. p = p->Flink;
  1487. NbiCompleteRequest (Request);
  1488. NbiFreeRequest (Device, Request);
  1489. }
  1490. return STATUS_SUCCESS;
  1491. } /* NbiStopAddressFile */
  1492. NTSTATUS
  1493. NbiCloseAddressFile(
  1494. IN PDEVICE Device,
  1495. IN PREQUEST Request
  1496. )
  1497. /*++
  1498. Routine Description:
  1499. This routine is called to close the addressfile pointed to by a file
  1500. object. If there is any activity to be run down, we will run it down
  1501. before we terminate the addressfile. We remove every connection and
  1502. datagram associated with this addressfile from the address database
  1503. and terminate their activity. Then, if there are no other outstanding
  1504. addressfiles open on this address, the address will go away.
  1505. Arguments:
  1506. Request - the close request.
  1507. Return Value:
  1508. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the
  1509. request does not point to a real address.
  1510. --*/
  1511. {
  1512. PADDRESS Address;
  1513. PADDRESS_FILE AddressFile;
  1514. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  1515. AddressFile->CloseRequest = Request;
  1516. //
  1517. // We assume that addressFile has already been verified
  1518. // at this point.
  1519. //
  1520. Address = AddressFile->Address;
  1521. CTEAssert (Address);
  1522. //
  1523. // Remove us from the access info for this address.
  1524. //
  1525. KeEnterCriticalRegion();
  1526. ExAcquireResourceExclusiveLite (&Device->AddressResource, TRUE);
  1527. #ifdef ISN_NT
  1528. IoRemoveShareAccess (AddressFile->FileObject, &Address->u.ShareAccess);
  1529. #endif
  1530. ExReleaseResourceLite (&Device->AddressResource);
  1531. KeLeaveCriticalRegion();
  1532. NbiStopAddressFile (AddressFile, Address);
  1533. NbiDereferenceAddressFile (AddressFile, AFREF_CREATE);
  1534. return STATUS_PENDING;
  1535. } /* NbiCloseAddressFile */
  1536. #if defined(_PNP_POWER)
  1537. PADAPTER_ADDRESS
  1538. NbiCreateAdapterAddress(
  1539. IN PCHAR AdapterMacAddress
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. This routine creates an adapter address sttuctures which stores
  1544. the netbios name of an adapter. the netbios name has 12 0's
  1545. followed by the mac address of the adapter.
  1546. Arguments:
  1547. Device - Pointer to the device context (which is really just
  1548. the device object with its extension) to be associated with the
  1549. address.
  1550. AdapterMacAddress - pointer to the adapter mac address given to us
  1551. by IPX.
  1552. Return Value:
  1553. The newly created address, or NULL if none can be allocated.
  1554. THIS ROUTINE MUST BE CALLED WITH THE DEVICE LOCK HELD.
  1555. --*/
  1556. {
  1557. PADAPTER_ADDRESS AdapterAddress;
  1558. CTELockHandle LockHandle;
  1559. PDEVICE Device = NbiDevice;
  1560. AdapterAddress = (PADAPTER_ADDRESS)NbiAllocateMemory (sizeof(ADAPTER_ADDRESS), MEMORY_ADAPTER_ADDRESS, "Adapter Address");
  1561. if (AdapterAddress == NULL) {
  1562. CTEAssert (AdapterMacAddress);
  1563. NB_DEBUG (ADDRESS, ("Create Adapter Address <%2.2x><%2.2x><%2.2x><%2.2x><%2.2x><%2.2x> failed\n",
  1564. (UCHAR) AdapterMacAddress[0],
  1565. (UCHAR) AdapterMacAddress[1],
  1566. (UCHAR) AdapterMacAddress[2],
  1567. (UCHAR) AdapterMacAddress[3],
  1568. (UCHAR) AdapterMacAddress[4],
  1569. (UCHAR) AdapterMacAddress[5]
  1570. ));
  1571. return NULL;
  1572. }
  1573. AdapterAddress->Type = NB_ADAPTER_ADDRESS_SIGNATURE;
  1574. AdapterAddress->Size = sizeof (ADDRESS);
  1575. RtlZeroMemory(AdapterAddress->NetbiosName, 10);
  1576. RtlCopyMemory(&AdapterAddress->NetbiosName[10], AdapterMacAddress, 6);
  1577. InsertTailList (&Device->AdapterAddressDatabase, &AdapterAddress->Linkage);
  1578. ++Device->AddressCounts[AdapterAddress->NetbiosName[0]];
  1579. return AdapterAddress;
  1580. } /* NbiCreateAdapterAddress */
  1581. NTSTATUS
  1582. NbiDestroyAdapterAddress(
  1583. IN PADAPTER_ADDRESS AdapterAddress OPTIONAL,
  1584. IN PCHAR AdapterMacAddress OPTIONAL
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine destroys the adapter address structure and removes it
  1589. from the list.
  1590. Arguments:
  1591. AdapterAddress - Pointer to an adapter address structure to be destroyed
  1592. NULL if AdapterMacAddress is given.
  1593. AdapterMacAddress - Mac Address of the adapter which just got deleted. so find
  1594. the corresponding adapter address structure and remove it.
  1595. NULL if AdapterAddress is supplied.
  1596. Return Value:
  1597. STATUS_SUCCESS or STATUS_UNSUCCESSFUL if address not found.
  1598. THIS ROUTINE ASSUMES THE THE DEVICE IS LOCK IS HELD BY THE CALLER
  1599. --*/
  1600. {
  1601. PDEVICE Device = NbiDevice;
  1602. CTELockHandle LockHandle;
  1603. UCHAR NetbiosName[NB_NETBIOS_NAME_SIZE];
  1604. //
  1605. CTEAssert( AdapterAddress || AdapterMacAddress );
  1606. if ( !AdapterAddress ) {
  1607. RtlZeroMemory( NetbiosName, 10);
  1608. RtlCopyMemory( &NetbiosName[10], AdapterMacAddress, 6 );
  1609. AdapterAddress = NbiFindAdapterAddress( NetbiosName, LOCK_ACQUIRED );
  1610. if ( !AdapterAddress ) {
  1611. return STATUS_UNSUCCESSFUL;
  1612. }
  1613. }
  1614. NB_DEBUG2 (ADDRESS, ("Destroy Adapter address %lx <%.16s>\n", AdapterAddress,AdapterAddress->NetbiosName));
  1615. RemoveEntryList (&AdapterAddress->Linkage);
  1616. ++Device->AddressCounts[AdapterAddress->NetbiosName[0]];
  1617. NbiFreeMemory (AdapterAddress, sizeof(ADAPTER_ADDRESS), MEMORY_ADAPTER_ADDRESS, "AdapterAddress");
  1618. return STATUS_SUCCESS;
  1619. } /* NbiDestroyAdapterAddress */
  1620. PADAPTER_ADDRESS
  1621. NbiFindAdapterAddress(
  1622. IN PCHAR NetbiosName,
  1623. IN BOOLEAN LockHeld
  1624. )
  1625. /*++
  1626. Routine Description:
  1627. This routine finds an adapter address ( netbios name ) for the given
  1628. AdapterMacAddress and returns a pointer to it. Note that no reference
  1629. is done on this address, so if this routine is called without the device
  1630. lock, the caller must not use this pointer directly.
  1631. Arguments:
  1632. NetbiosName - NetbiosName to be found.
  1633. LockHeld - is device lock already held or not.
  1634. Return Value:
  1635. Pointer to the adapter address if found, NULL otherwise.
  1636. --*/
  1637. {
  1638. PLIST_ENTRY p;
  1639. CTELockHandle LockHandle;
  1640. PADAPTER_ADDRESS AdapterAddress;
  1641. PDEVICE Device = NbiDevice;
  1642. if ( !LockHeld ) {
  1643. NB_GET_LOCK( &Device->Lock, &LockHandle );
  1644. }
  1645. for ( p = Device->AdapterAddressDatabase.Flink;
  1646. p != &Device->AdapterAddressDatabase;
  1647. p = p->Flink ) {
  1648. AdapterAddress = CONTAINING_RECORD( p, ADAPTER_ADDRESS, Linkage );
  1649. if ( RtlEqualMemory(
  1650. NetbiosName,
  1651. AdapterAddress->NetbiosName,
  1652. NB_NETBIOS_NAME_SIZE ) ) {
  1653. break;
  1654. }
  1655. }
  1656. if ( !LockHeld ) {
  1657. NB_FREE_LOCK( &Device->Lock, LockHandle );
  1658. }
  1659. if ( p == &Device->AdapterAddressDatabase ) {
  1660. return NULL;
  1661. } else {
  1662. return AdapterAddress;
  1663. }
  1664. } /* NbiFindAdapterAddress */
  1665. #endif _PNP_POWER