Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3094 lines
86 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. address.c
  5. Abstract:
  6. This module contains code which implements the TP_ADDRESS object.
  7. Routines are provided to create, destroy, reference, and dereference,
  8. transport address objects.
  9. Author:
  10. David Beaver (dbeaver) 1-July-1991
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #if DBG
  18. #define NbfDbgShowAddr(TNA)\
  19. { \
  20. if ((TNA) == NULL) { \
  21. NbfPrint0("<NetBios broadcast>\n"); \
  22. } else { \
  23. NbfPrint6("%c %c %c %c %d (%c)\n", \
  24. (TNA)->NetbiosName[0], \
  25. (TNA)->NetbiosName[1], \
  26. (TNA)->NetbiosName[4], \
  27. (TNA)->NetbiosName[6], \
  28. (TNA)->NetbiosName[15], \
  29. (TNA)->NetbiosNameType + 'A'); \
  30. } \
  31. }
  32. #else
  33. #define NbfDbgShowAddr(TNA)
  34. #endif
  35. //
  36. // Map all generic accesses to the same one.
  37. //
  38. STATIC GENERIC_MAPPING AddressGenericMapping =
  39. { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  40. VOID
  41. AddressTimeoutHandler(
  42. IN PKDPC Dpc,
  43. IN PVOID DeferredContext,
  44. IN PVOID SystemArgument1,
  45. IN PVOID SystemArgument2
  46. )
  47. /*++
  48. Routine Description:
  49. This routine is executed as a DPC at DISPATCH_LEVEL when the timeout
  50. period for the ADD_NAME_QUERY/ADD_NAME_RECOGNIZED protocol expires.
  51. The retry count in the Address object is decremented, and if it reaches 0,
  52. the address is registered. If the retry count has not reached zero,
  53. then the ADD NAME QUERY is retried.
  54. Arguments:
  55. Dpc - Pointer to a system DPC object.
  56. DeferredContext - Pointer to the TP_ADDRESS block representing the
  57. address that is being registered.
  58. SystemArgument1 - Not used.
  59. SystemArgument2 - Not used.
  60. Return Value:
  61. none.
  62. --*/
  63. {
  64. PTP_ADDRESS_FILE addressFile;
  65. PTP_ADDRESS address;
  66. PDEVICE_CONTEXT DeviceContext;
  67. PLIST_ENTRY p;
  68. LARGE_INTEGER timeout;
  69. Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings
  70. ENTER_NBF;
  71. address = (PTP_ADDRESS)DeferredContext;
  72. DeviceContext = address->Provider;
  73. //
  74. // We are waiting for an ADD_NAME_RECOGNIZED indicating that there is a
  75. // conflict. Decrement the retry count, and if it dropped to zero,
  76. // then we've waited a sufficiently long time. If there was no conflict,
  77. // complete all waiting file opens for the address.
  78. //
  79. ACQUIRE_DPC_SPIN_LOCK (&address->SpinLock);
  80. if ((address->Flags & ADDRESS_FLAGS_QUICK_REREGISTER) != 0) {
  81. BOOLEAN DuplicateName;
  82. PTP_CONNECTION Connection;
  83. DuplicateName = ((address->Flags & (ADDRESS_FLAGS_DUPLICATE_NAME|ADDRESS_FLAGS_CONFLICT)) != 0);
  84. for (p=address->ConnectionDatabase.Flink;
  85. p != &address->ConnectionDatabase;
  86. p=p->Flink) {
  87. Connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressList);
  88. if ((Connection->Flags2 & CONNECTION_FLAGS2_STOPPING) != 0) {
  89. continue;
  90. }
  91. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  92. if ((Connection->Flags2 & CONNECTION_FLAGS2_W_ADDRESS) != 0) {
  93. if (DuplicateName) {
  94. NbfStopConnection (Connection, STATUS_DUPLICATE_NAME);
  95. } else {
  96. //
  97. // Continue with the connection attempt.
  98. //
  99. ULONG NameQueryTimeout;
  100. ACQUIRE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  101. Connection->Flags2 &= ~CONNECTION_FLAGS2_W_ADDRESS;
  102. RELEASE_DPC_C_SPIN_LOCK (&Connection->SpinLock);
  103. KeQueryTickCount (&Connection->ConnectStartTime);
  104. NameQueryTimeout = Connection->Provider->NameQueryTimeout;
  105. if (Connection->Provider->MacInfo.MediumAsync &&
  106. !Connection->Provider->MediumSpeedAccurate) {
  107. NameQueryTimeout = NAME_QUERY_TIMEOUT / 10;
  108. }
  109. NbfSendNameQuery (
  110. Connection,
  111. TRUE);
  112. NbfStartConnectionTimer (
  113. Connection,
  114. ConnectionEstablishmentTimeout,
  115. NameQueryTimeout);
  116. }
  117. }
  118. ACQUIRE_DPC_SPIN_LOCK (&address->SpinLock);
  119. }
  120. address->Flags &= ~ADDRESS_FLAGS_QUICK_REREGISTER;
  121. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  122. NbfDereferenceAddress ("Timer, registered", address, AREF_TIMER);
  123. } else if ((address->Flags & (ADDRESS_FLAGS_DUPLICATE_NAME|ADDRESS_FLAGS_CONFLICT)) != 0) {
  124. PIRP irp;
  125. //
  126. // the address registration has failed. We signal the user in
  127. // the normal way (by failing the open of the address). Now clean up
  128. // the transport's data structures.
  129. //
  130. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  131. NbfPrint1 ("AddressTimeoutHandler %lx: duplicate\n", address);
  132. }
  133. address->Flags &= ~ADDRESS_FLAGS_REGISTERING;
  134. // address->Flags |= ADDRESS_FLAGS_STOPPING;
  135. //
  136. // This is probably all overkill, the
  137. // uframes handler will already have called
  138. // NbfStopAddress, which will tear off all
  139. // the address files etc., and set the
  140. // STOPPING flag which prevents further opens.
  141. //
  142. p = address->AddressFileDatabase.Flink;
  143. while (p != &address->AddressFileDatabase) {
  144. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  145. p = p->Flink;
  146. if (addressFile->Irp != NULL) {
  147. irp = addressFile->Irp;
  148. addressFile->Irp = NULL;
  149. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  150. irp->IoStatus.Information = 0;
  151. irp->IoStatus.Status = STATUS_DUPLICATE_NAME;
  152. LEAVE_NBF;
  153. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  154. ENTER_NBF;
  155. NbfStopAddressFile (addressFile, address);
  156. ACQUIRE_DPC_SPIN_LOCK (&address->SpinLock);
  157. }
  158. }
  159. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  160. //
  161. // There will be no more timer events happening, so we dereference the
  162. // address to account for the timer.
  163. //
  164. NbfStopAddress (address);
  165. NbfDereferenceAddress ("Timer, dup address", address, AREF_TIMER);
  166. } else {
  167. //
  168. // has the address registration succeeded?
  169. //
  170. if (--(address->Retries) <= 0) { // if retry count exhausted.
  171. PIRP irp;
  172. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  173. NbfPrint1 ("AddressTimeoutHandler %lx: successful.\n", address);
  174. }
  175. address->Flags &= ~ADDRESS_FLAGS_REGISTERING;
  176. p = address->AddressFileDatabase.Flink;
  177. while (p != &address->AddressFileDatabase) {
  178. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  179. p = p->Flink;
  180. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  181. NbfPrint3 ("AddressTimeoutHandler %lx: Completing IRP %lx for file %lx\n",
  182. address,
  183. addressFile->Irp,
  184. addressFile);
  185. }
  186. if (addressFile->Irp != NULL) {
  187. irp = addressFile->Irp;
  188. addressFile->Irp = NULL;
  189. addressFile->State = ADDRESSFILE_STATE_OPEN;
  190. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  191. irp->IoStatus.Information = 0;
  192. irp->IoStatus.Status = STATUS_SUCCESS;
  193. LEAVE_NBF;
  194. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  195. ENTER_NBF;
  196. ACQUIRE_DPC_SPIN_LOCK (&address->SpinLock);
  197. }
  198. }
  199. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  200. //
  201. // Dereference the address if we're all done.
  202. //
  203. NbfDereferenceAddress ("Timer, registered", address, AREF_TIMER);
  204. } else {
  205. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  206. NbfPrint2 ("AddressTimeoutHandler %lx: step %x.\n",
  207. address,
  208. DeviceContext->AddNameQueryRetries - address->Retries);
  209. }
  210. //
  211. // restart the timer if we haven't yet completed registration
  212. //
  213. RELEASE_DPC_SPIN_LOCK (&address->SpinLock);
  214. timeout.LowPart = (ULONG)(-(LONG)DeviceContext->AddNameQueryTimeout);
  215. timeout.HighPart = -1;
  216. KeSetTimer (&address->Timer,*(PTIME)&timeout, &address->Dpc);
  217. (VOID)NbfSendAddNameQuery (address); // send another ADD_NAME_QUERY.
  218. }
  219. }
  220. LEAVE_NBF;
  221. return;
  222. } /* AddressTimeoutHandler */
  223. TDI_ADDRESS_NETBIOS *
  224. NbfParseTdiAddress(
  225. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
  226. IN BOOLEAN BroadcastAddressOk
  227. )
  228. /*++
  229. Routine Description:
  230. This routine scans a TRANSPORT_ADDRESS, looking for an address
  231. of type TDI_ADDRESS_TYPE_NETBIOS.
  232. Arguments:
  233. Transport - The generic TDI address.
  234. BroadcastAddressOk - TRUE if we should return the broadcast
  235. address if found. If so, a value of (PVOID)-1 indicates
  236. the broadcast address.
  237. Return Value:
  238. A pointer to the Netbios address, or NULL if none is found,
  239. or (PVOID)-1 if the broadcast address is found.
  240. --*/
  241. {
  242. TA_ADDRESS * addressName;
  243. INT i;
  244. addressName = &TransportAddress->Address[0];
  245. //
  246. // The name can be passed with multiple entries; we'll take and use only
  247. // the Netbios one.
  248. //
  249. for (i=0;i<TransportAddress->TAAddressCount;i++) {
  250. if (addressName->AddressType == TDI_ADDRESS_TYPE_NETBIOS) {
  251. if ((addressName->AddressLength == 0) &&
  252. BroadcastAddressOk) {
  253. return (PVOID)-1;
  254. } else if (addressName->AddressLength ==
  255. sizeof(TDI_ADDRESS_NETBIOS)) {
  256. return((TDI_ADDRESS_NETBIOS *)(addressName->Address));
  257. }
  258. }
  259. addressName = (TA_ADDRESS *)(addressName->Address +
  260. addressName->AddressLength);
  261. }
  262. return NULL;
  263. } /* NbfParseTdiAddress */
  264. BOOLEAN
  265. NbfValidateTdiAddress(
  266. IN TRANSPORT_ADDRESS UNALIGNED * TransportAddress,
  267. IN ULONG TransportAddressLength
  268. )
  269. /*++
  270. Routine Description:
  271. This routine scans a TRANSPORT_ADDRESS, verifying that the
  272. components of the address do not extend past the specified
  273. length.
  274. Arguments:
  275. TransportAddress - The generic TDI address.
  276. TransportAddressLength - The specific length of TransportAddress.
  277. Return Value:
  278. TRUE if the address is valid, FALSE otherwise.
  279. --*/
  280. {
  281. PUCHAR AddressEnd = ((PUCHAR)TransportAddress) + TransportAddressLength;
  282. TA_ADDRESS * addressName;
  283. INT i;
  284. if (TransportAddressLength < sizeof(TransportAddress->TAAddressCount)) {
  285. NbfPrint0 ("NbfValidateTdiAddress: runt address\n");
  286. return FALSE;
  287. }
  288. addressName = &TransportAddress->Address[0];
  289. for (i=0;i<TransportAddress->TAAddressCount;i++) {
  290. if (addressName->Address > AddressEnd) {
  291. NbfPrint0 ("NbfValidateTdiAddress: address too short\n");
  292. return FALSE;
  293. }
  294. addressName = (TA_ADDRESS *)(addressName->Address +
  295. addressName->AddressLength);
  296. }
  297. if ((PUCHAR)addressName > AddressEnd) {
  298. NbfPrint0 ("NbfValidateTdiAddress: address too short\n");
  299. return FALSE;
  300. }
  301. return TRUE;
  302. } /* NbfValidateTdiAddress */
  303. NTSTATUS
  304. NbfOpenAddress(
  305. IN PDEVICE_OBJECT DeviceObject,
  306. IN PIRP Irp,
  307. IN PIO_STACK_LOCATION IrpSp
  308. )
  309. /*++
  310. Routine Description:
  311. This routine opens a file that points to an existing address object, or, if
  312. the object doesn't exist, creates it (note that creation of the address
  313. object includes registering the address, and may take many seconds to
  314. complete, depending upon system configuration).
  315. If the address already exists, and it has an ACL associated with it, the
  316. ACL is checked for access rights before allowing creation of the address.
  317. Arguments:
  318. DeviceObject - pointer to the device object describing the NBF transport.
  319. Irp - a pointer to the Irp used for the creation of the address.
  320. IrpSp - a pointer to the Irp stack location.
  321. Return Value:
  322. NTSTATUS - status of operation.
  323. --*/
  324. {
  325. PDEVICE_CONTEXT DeviceContext;
  326. NTSTATUS status;
  327. PTP_ADDRESS address;
  328. PTP_ADDRESS_FILE addressFile;
  329. PNBF_NETBIOS_ADDRESS networkName; // Network name string.
  330. PFILE_FULL_EA_INFORMATION ea;
  331. TRANSPORT_ADDRESS UNALIGNED *name;
  332. TDI_ADDRESS_NETBIOS *netbiosName;
  333. ULONG DesiredShareAccess;
  334. KIRQL oldirql;
  335. PACCESS_STATE AccessState;
  336. ACCESS_MASK GrantedAccess;
  337. BOOLEAN AccessAllowed;
  338. BOOLEAN QuickAdd = FALSE;
  339. DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
  340. //
  341. // The network name is in the EA, passed in AssociatedIrp.SystemBuffer
  342. //
  343. ea = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  344. if (ea == NULL) {
  345. NbfPrint1("OpenAddress: IRP %lx has no EA\n", Irp);
  346. return STATUS_INVALID_ADDRESS_COMPONENT;
  347. }
  348. //
  349. // this may be a valid name; parse the name from the EA and use it if OK.
  350. //
  351. name = (TRANSPORT_ADDRESS UNALIGNED *)&ea->EaName[ea->EaNameLength+1];
  352. if (!NbfValidateTdiAddress(name, ea->EaValueLength)) {
  353. return STATUS_INVALID_ADDRESS_COMPONENT;
  354. }
  355. //
  356. // The name can have with multiple entries; we'll use the Netbios one.
  357. // This call returns NULL if not Netbios address is found, (PVOID)-1
  358. // if it is the broadcast address, and a pointer to a Netbios
  359. // address otherwise.
  360. //
  361. netbiosName = NbfParseTdiAddress(name, TRUE);
  362. if (netbiosName != NULL) {
  363. if (netbiosName != (PVOID)-1) {
  364. networkName = (PNBF_NETBIOS_ADDRESS)ExAllocatePoolWithTag (
  365. NonPagedPool,
  366. sizeof (NBF_NETBIOS_ADDRESS),
  367. NBF_MEM_TAG_NETBIOS_NAME);
  368. if (networkName == NULL) {
  369. PANIC ("NbfOpenAddress: PANIC! could not allocate networkName!\n");
  370. NbfWriteResourceErrorLog(
  371. DeviceContext,
  372. EVENT_TRANSPORT_RESOURCE_POOL,
  373. 1,
  374. sizeof(TA_NETBIOS_ADDRESS),
  375. ADDRESS_RESOURCE_ID);
  376. return STATUS_INSUFFICIENT_RESOURCES;
  377. }
  378. //
  379. // get the name to local storage
  380. //
  381. if ((netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP) ||
  382. (netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP)) {
  383. networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_GROUP;
  384. } else {
  385. networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  386. }
  387. RtlCopyMemory (networkName->NetbiosName, netbiosName->NetbiosName, 16);
  388. if ((netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE) ||
  389. (netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP)) {
  390. QuickAdd = TRUE;
  391. }
  392. } else {
  393. networkName = NULL;
  394. }
  395. } else {
  396. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  397. NbfPrint1("OpenAddress: IRP %lx has no NETBIOS address\n", Irp);
  398. }
  399. return STATUS_INVALID_ADDRESS_COMPONENT;
  400. }
  401. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  402. NbfPrint1 ("OpenAddress %s: ",
  403. ((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  404. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  405. "shared" : "exclusive");
  406. NbfDbgShowAddr (networkName);
  407. }
  408. //
  409. // get an address file structure to represent this address.
  410. //
  411. status = NbfCreateAddressFile (DeviceContext, &addressFile);
  412. if (!NT_SUCCESS (status)) {
  413. if (networkName != NULL) {
  414. ExFreePool (networkName);
  415. }
  416. return status;
  417. }
  418. //
  419. // See if this address is already established. This call automatically
  420. // increments the reference count on the address so that it won't disappear
  421. // from underneath us after this call but before we have a chance to use it.
  422. //
  423. // To ensure that we don't create two address objects for the
  424. // same address, we hold the device context AddressResource until
  425. // we have found the address or created a new one.
  426. //
  427. ACQUIRE_RESOURCE_EXCLUSIVE (&DeviceContext->AddressResource, TRUE);
  428. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  429. address = NbfLookupAddress (DeviceContext, networkName);
  430. if (address == NULL) {
  431. //
  432. // This address doesn't exist. Create it, and start the process of
  433. // registering it.
  434. //
  435. status = NbfCreateAddress (
  436. DeviceContext,
  437. networkName,
  438. &address);
  439. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  440. if (NT_SUCCESS (status)) {
  441. //
  442. // Initialize the shared access now. We use read access
  443. // to control all access.
  444. //
  445. DesiredShareAccess = (ULONG)
  446. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  447. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  448. FILE_SHARE_READ : 0);
  449. IoSetShareAccess(
  450. FILE_READ_DATA,
  451. DesiredShareAccess,
  452. IrpSp->FileObject,
  453. &address->u.ShareAccess);
  454. //
  455. // Assign the security descriptor (need to do this with
  456. // the spinlock released because the descriptor is not
  457. // mapped. Need to synchronize Assign and Access).
  458. //
  459. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  460. status = SeAssignSecurity(
  461. NULL, // parent descriptor
  462. AccessState->SecurityDescriptor,
  463. &address->SecurityDescriptor,
  464. FALSE, // is directory
  465. &AccessState->SubjectSecurityContext,
  466. &AddressGenericMapping,
  467. PagedPool);
  468. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  469. NbfPrint3 ("Assign security A %lx AF %lx, status %lx\n",
  470. address,
  471. addressFile,
  472. status);
  473. }
  474. if (!NT_SUCCESS(status)) {
  475. //
  476. // Error, return status.
  477. //
  478. IoRemoveShareAccess (IrpSp->FileObject, &address->u.ShareAccess);
  479. // Mark as stopping so that someone does not ref it again
  480. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  481. address->Flags |= ADDRESS_FLAGS_STOPPING;
  482. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  483. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  484. NbfDereferenceAddress ("Device context stopping", address, AREF_TEMP_CREATE);
  485. NbfDereferenceAddressFile (addressFile);
  486. return status;
  487. }
  488. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  489. //
  490. // if the adapter isn't ready, we can't do any of this; get out
  491. //
  492. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  493. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  494. NbfPrint3("OpenAddress A %lx AF %lx: DeviceContext %lx not open\n",
  495. address,
  496. addressFile,
  497. DeviceContext);
  498. }
  499. NbfDereferenceAddressFile (addressFile);
  500. status = STATUS_DEVICE_NOT_READY;
  501. } else {
  502. IrpSp->FileObject->FsContext = (PVOID)addressFile;
  503. IrpSp->FileObject->FsContext2 =
  504. (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  505. addressFile->FileObject = IrpSp->FileObject;
  506. addressFile->Irp = Irp;
  507. addressFile->Address = address;
  508. NbfReferenceAddress("Opened new", address, AREF_OPEN);
  509. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  510. NbfPrint2("OpenAddress A %lx AF %lx: created.\n",
  511. address,
  512. addressFile);
  513. }
  514. ExInterlockedInsertTailList(
  515. &address->AddressFileDatabase,
  516. &addressFile->Linkage,
  517. &address->SpinLock);
  518. //
  519. // Begin address registration unless this is the broadcast
  520. // address (which is a "fake" address with no corresponding
  521. // Netbios address) or the reserved address, which we know
  522. // is unique since it is based on the adapter address.
  523. //
  524. // Also, for "quick" add names, do not register.
  525. //
  526. if ((networkName != NULL) &&
  527. (!RtlEqualMemory (networkName->NetbiosName,
  528. DeviceContext->ReservedNetBIOSAddress,
  529. NETBIOS_NAME_LENGTH)) &&
  530. (!QuickAdd)) {
  531. NbfRegisterAddress (address); // begin address registration.
  532. status = STATUS_PENDING;
  533. } else {
  534. address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG;
  535. addressFile->Irp = NULL;
  536. addressFile->State = ADDRESSFILE_STATE_OPEN;
  537. status = STATUS_SUCCESS;
  538. }
  539. }
  540. NbfDereferenceAddress("temp create", address, AREF_TEMP_CREATE);
  541. } else {
  542. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  543. //
  544. // If the address could not be created, and is not in the process of
  545. // being created, then we can't open up an address.
  546. //
  547. if (networkName != NULL) {
  548. ExFreePool (networkName);
  549. }
  550. NbfDereferenceAddressFile (addressFile);
  551. }
  552. } else {
  553. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  554. //
  555. // The address already exists. Check the ACL and see if we
  556. // can access it. If so, simply use this address as our address.
  557. //
  558. AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
  559. AccessAllowed = SeAccessCheck(
  560. address->SecurityDescriptor,
  561. &AccessState->SubjectSecurityContext,
  562. FALSE, // lock tokens
  563. IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
  564. (ACCESS_MASK)0, // previously granted
  565. NULL, // privileges
  566. &AddressGenericMapping,
  567. Irp->RequestorMode,
  568. &GrantedAccess,
  569. &status);
  570. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  571. NbfPrint4 ("Access check A %lx AF %lx, %s (%lx)\n",
  572. address,
  573. addressFile,
  574. AccessAllowed ? "allowed" : "not allowed",
  575. status);
  576. }
  577. if (AccessAllowed) {
  578. //
  579. // Access was successful, make sure Status is right.
  580. //
  581. status = STATUS_SUCCESS;
  582. // Transfer the access masks from what is desired to what is granted
  583. AccessState->PreviouslyGrantedAccess |= GrantedAccess;
  584. AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
  585. //
  586. // Compare DesiredAccess to GrantedAccess?
  587. //
  588. //
  589. // Check that the name is of the correct type (unique vs. group)
  590. // We don't need to check this for the broadcast address.
  591. //
  592. // This code is structured funny, the only reason
  593. // this is inside this if is to avoid indenting too much.
  594. //
  595. if (networkName != NULL) {
  596. if (address->NetworkName->NetbiosNameType !=
  597. networkName->NetbiosNameType) {
  598. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  599. NbfPrint2 ("Address types differ: old %c, new %c\n",
  600. address->NetworkName->NetbiosNameType + 'A',
  601. networkName->NetbiosNameType + 'A');
  602. }
  603. status = STATUS_DUPLICATE_NAME;
  604. }
  605. }
  606. }
  607. if (!NT_SUCCESS (status)) {
  608. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  609. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  610. NbfPrint2("OpenAddress A %lx AF %lx: ACL bad.\n",
  611. address,
  612. addressFile);
  613. }
  614. NbfDereferenceAddressFile (addressFile);
  615. } else {
  616. //
  617. // Now check that we can obtain the desired share
  618. // access. We use read access to control all access.
  619. //
  620. DesiredShareAccess = (ULONG)
  621. (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  622. (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  623. FILE_SHARE_READ : 0);
  624. status = IoCheckShareAccess(
  625. FILE_READ_DATA,
  626. DesiredShareAccess,
  627. IrpSp->FileObject,
  628. &address->u.ShareAccess,
  629. TRUE);
  630. if (!NT_SUCCESS (status)) {
  631. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  632. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  633. NbfPrint2("OpenAddress A %lx AF %lx: ShareAccess problem.\n",
  634. address,
  635. addressFile);
  636. }
  637. NbfDereferenceAddressFile (addressFile);
  638. } else {
  639. RELEASE_RESOURCE (&DeviceContext->AddressResource);
  640. ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
  641. //
  642. // now, if the address registered, we simply return success after
  643. // pointing the file object at the address file (which points to
  644. // the address). If the address registration is pending, we mark
  645. // the registration pending and let the registration completion
  646. // routine complete the open. If the address is bad, we simply
  647. // fail the open.
  648. //
  649. if ((address->Flags &
  650. (ADDRESS_FLAGS_CONFLICT |
  651. ADDRESS_FLAGS_REGISTERING |
  652. ADDRESS_FLAGS_DEREGISTERING |
  653. ADDRESS_FLAGS_DUPLICATE_NAME |
  654. ADDRESS_FLAGS_NEEDS_REG |
  655. ADDRESS_FLAGS_STOPPING |
  656. ADDRESS_FLAGS_BAD_ADDRESS |
  657. ADDRESS_FLAGS_CLOSED)) == 0) {
  658. InsertTailList (
  659. &address->AddressFileDatabase,
  660. &addressFile->Linkage);
  661. addressFile->Irp = NULL;
  662. addressFile->Address = address;
  663. addressFile->FileObject = IrpSp->FileObject;
  664. addressFile->State = ADDRESSFILE_STATE_OPEN;
  665. NbfReferenceAddress("open ready", address, AREF_OPEN);
  666. IrpSp->FileObject->FsContext = (PVOID)addressFile;
  667. IrpSp->FileObject->FsContext2 =
  668. (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  669. RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
  670. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  671. NbfPrint2("OpenAddress A %lx AF %lx: address ready.\n",
  672. address,
  673. addressFile);
  674. }
  675. status = STATUS_SUCCESS;
  676. } else {
  677. //
  678. // if the address is still registering, make the open pending.
  679. //
  680. if ((address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_NEEDS_REG)) != 0) {
  681. InsertTailList (
  682. &address->AddressFileDatabase,
  683. &addressFile->Linkage);
  684. addressFile->Irp = Irp;
  685. addressFile->Address = address;
  686. addressFile->FileObject = IrpSp->FileObject;
  687. NbfReferenceAddress("open registering", address, AREF_OPEN);
  688. IrpSp->FileObject->FsContext = (PVOID)addressFile;
  689. IrpSp->FileObject->FsContext2 =
  690. (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  691. RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
  692. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  693. NbfPrint2("OpenAddress A %lx AF %lx: address registering.\n",
  694. address,
  695. addressFile);
  696. }
  697. status = STATUS_PENDING;
  698. } else {
  699. if ((address->Flags & ADDRESS_FLAGS_CONFLICT) != 0) {
  700. status = STATUS_DUPLICATE_NAME;
  701. } else {
  702. status = STATUS_DRIVER_INTERNAL_ERROR;
  703. }
  704. RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
  705. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  706. NbfPrint3("OpenAddress A %lx AF %lx: address flags %lx.\n",
  707. address,
  708. addressFile,
  709. address->Flags);
  710. }
  711. NbfDereferenceAddressFile (addressFile);
  712. }
  713. }
  714. }
  715. }
  716. //
  717. // This isn't needed since it was not used in the
  718. // creation of the address.
  719. //
  720. if (networkName != NULL) {
  721. ExFreePool (networkName);
  722. }
  723. //
  724. // Remove the reference from NbfLookupAddress.
  725. //
  726. NbfDereferenceAddress ("Done opening", address, AREF_LOOKUP);
  727. }
  728. return status;
  729. } /* NbfOpenAddress */
  730. VOID
  731. NbfAllocateAddress(
  732. IN PDEVICE_CONTEXT DeviceContext,
  733. OUT PTP_ADDRESS *TransportAddress
  734. )
  735. /*++
  736. Routine Description:
  737. This routine allocates storage for a transport address. Some minimal
  738. initialization is done on the address.
  739. NOTE: This routine is called with the device context spinlock
  740. held, or at such a time as synchronization is unnecessary.
  741. Arguments:
  742. DeviceContext - Pointer to the device context (which is really just
  743. the device object with its extension) to be associated with the
  744. address.
  745. Address - Pointer to a place where this routine will return a pointer
  746. to a transport address structure. Returns NULL if no storage
  747. can be allocated.
  748. Return Value:
  749. None.
  750. --*/
  751. {
  752. PTP_ADDRESS Address;
  753. PSEND_PACKET_TAG SendTag;
  754. NDIS_STATUS NdisStatus;
  755. PNDIS_PACKET NdisPacket;
  756. PNDIS_BUFFER NdisBuffer;
  757. if ((DeviceContext->MemoryLimit != 0) &&
  758. ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS)) >
  759. DeviceContext->MemoryLimit)) {
  760. PANIC("NBF: Could not allocate address: limit\n");
  761. NbfWriteResourceErrorLog(
  762. DeviceContext,
  763. EVENT_TRANSPORT_RESOURCE_LIMIT,
  764. 101,
  765. sizeof(TP_ADDRESS),
  766. ADDRESS_RESOURCE_ID);
  767. *TransportAddress = NULL;
  768. return;
  769. }
  770. Address = (PTP_ADDRESS)ExAllocatePoolWithTag (
  771. NonPagedPool,
  772. sizeof (TP_ADDRESS),
  773. NBF_MEM_TAG_TP_ADDRESS);
  774. if (Address == NULL) {
  775. PANIC("NBF: Could not allocate address: no pool\n");
  776. NbfWriteResourceErrorLog(
  777. DeviceContext,
  778. EVENT_TRANSPORT_RESOURCE_POOL,
  779. 201,
  780. sizeof(TP_ADDRESS),
  781. ADDRESS_RESOURCE_ID);
  782. *TransportAddress = NULL;
  783. return;
  784. }
  785. RtlZeroMemory (Address, sizeof(TP_ADDRESS));
  786. // To track packet pools in NDIS allocated on NBF's behalf
  787. #if NDIS_POOL_TAGGING
  788. Address->UIFramePoolHandle = (NDIS_HANDLE) NDIS_PACKET_POOL_TAG_FOR_NBF;
  789. #endif
  790. NdisAllocatePacketPoolEx (
  791. &NdisStatus,
  792. &Address->UIFramePoolHandle,
  793. 1,
  794. 0,
  795. sizeof(SEND_PACKET_TAG));
  796. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  797. PANIC("NBF: Could not allocate address UI frame pool: no pool\n");
  798. NbfWriteResourceErrorLog(
  799. DeviceContext,
  800. EVENT_TRANSPORT_RESOURCE_POOL,
  801. 311,
  802. sizeof(SEND_PACKET_TAG),
  803. ADDRESS_RESOURCE_ID);
  804. ExFreePool (Address);
  805. *TransportAddress = NULL;
  806. return;
  807. }
  808. NdisSetPacketPoolProtocolId (Address->UIFramePoolHandle, NDIS_PROTOCOL_ID_NBF);
  809. //
  810. // This code is similar to NbfAllocateUIFrame.
  811. //
  812. Address->UIFrame = (PTP_UI_FRAME) ExAllocatePoolWithTag (
  813. NonPagedPool,
  814. DeviceContext->UIFrameLength,
  815. NBF_MEM_TAG_TP_UI_FRAME);
  816. if (Address->UIFrame == NULL) {
  817. PANIC("NBF: Could not allocate address UI frame: no pool\n");
  818. NbfWriteResourceErrorLog(
  819. DeviceContext,
  820. EVENT_TRANSPORT_RESOURCE_POOL,
  821. 411,
  822. DeviceContext->UIFrameLength,
  823. ADDRESS_RESOURCE_ID);
  824. NdisFreePacketPool (Address->UIFramePoolHandle);
  825. ExFreePool (Address);
  826. *TransportAddress = NULL;
  827. return;
  828. }
  829. RtlZeroMemory (Address->UIFrame, DeviceContext->UIFrameLength);
  830. NdisAllocatePacket (
  831. &NdisStatus,
  832. &NdisPacket,
  833. Address->UIFramePoolHandle);
  834. ASSERT (NdisStatus == NDIS_STATUS_SUCCESS);
  835. Address->UIFrame->NdisPacket = NdisPacket;
  836. Address->UIFrame->DataBuffer = NULL;
  837. SendTag = (PSEND_PACKET_TAG)NdisPacket->ProtocolReserved;
  838. SendTag->Type = TYPE_ADDRESS_FRAME;
  839. SendTag->Owner = (PVOID)Address;
  840. SendTag->Frame = Address->UIFrame;
  841. //
  842. // Make the packet header known to the packet descriptor
  843. //
  844. NdisAllocateBuffer(
  845. &NdisStatus,
  846. &NdisBuffer,
  847. DeviceContext->NdisBufferPool,
  848. Address->UIFrame->Header,
  849. DeviceContext->UIFrameHeaderLength);
  850. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  851. PANIC("NBF: Could not allocate address UI frame buffer: no pool\n");
  852. NbfWriteResourceErrorLog(
  853. DeviceContext,
  854. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  855. 511,
  856. 0,
  857. UI_FRAME_RESOURCE_ID);
  858. ExFreePool (Address->UIFrame);
  859. NdisFreePacket (Address->UIFrame->NdisPacket);
  860. NdisFreePacketPool (Address->UIFramePoolHandle);
  861. ExFreePool (Address);
  862. *TransportAddress = NULL;
  863. return;
  864. }
  865. NdisChainBufferAtFront (NdisPacket, NdisBuffer);
  866. DeviceContext->MemoryUsage +=
  867. sizeof(TP_ADDRESS) +
  868. sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG) +
  869. DeviceContext->UIFrameLength;
  870. ++DeviceContext->AddressAllocated;
  871. Address->Type = NBF_ADDRESS_SIGNATURE;
  872. Address->Size = sizeof (TP_ADDRESS);
  873. Address->Provider = DeviceContext;
  874. KeInitializeSpinLock (&Address->SpinLock);
  875. // KeInitializeSpinLock (&Address->Interlock);
  876. InitializeListHead (&Address->ConnectionDatabase);
  877. InitializeListHead (&Address->AddressFileDatabase);
  878. InitializeListHead (&Address->SendDatagramQueue);
  879. KeInitializeDpc (&Address->Dpc, AddressTimeoutHandler, (PVOID)Address);
  880. KeInitializeTimer (&Address->Timer);
  881. //
  882. // For each address, allocate a receive packet and a receive buffer.
  883. //
  884. NbfAddReceivePacket (DeviceContext);
  885. NbfAddReceiveBuffer (DeviceContext);
  886. *TransportAddress = Address;
  887. } /* NbfAllocateAddress */
  888. VOID
  889. NbfDeallocateAddress(
  890. IN PDEVICE_CONTEXT DeviceContext,
  891. IN PTP_ADDRESS TransportAddress
  892. )
  893. /*++
  894. Routine Description:
  895. This routine frees storage for a transport address.
  896. NOTE: This routine is called with the device context spinlock
  897. held, or at such a time as synchronization is unnecessary.
  898. Arguments:
  899. DeviceContext - Pointer to the device context (which is really just
  900. the device object with its extension) to be associated with the
  901. address.
  902. Address - Pointer to a transport address structure.
  903. Return Value:
  904. None.
  905. --*/
  906. {
  907. PNDIS_BUFFER NdisBuffer;
  908. NdisUnchainBufferAtFront (TransportAddress->UIFrame->NdisPacket, &NdisBuffer);
  909. if (NdisBuffer != NULL) {
  910. NdisFreeBuffer (NdisBuffer);
  911. }
  912. NdisFreePacket(TransportAddress->UIFrame->NdisPacket);
  913. ExFreePool (TransportAddress->UIFrame);
  914. NdisFreePacketPool (TransportAddress->UIFramePoolHandle);
  915. ExFreePool (TransportAddress);
  916. --DeviceContext->AddressAllocated;
  917. DeviceContext->MemoryUsage -=
  918. sizeof(TP_ADDRESS) +
  919. sizeof(NDIS_PACKET) + sizeof(SEND_PACKET_TAG) +
  920. DeviceContext->UIFrameLength;
  921. //
  922. // Remove the resources which allocating this caused.
  923. //
  924. NbfRemoveReceivePacket (DeviceContext);
  925. NbfRemoveReceiveBuffer (DeviceContext);
  926. } /* NbfDeallocateAddress */
  927. NTSTATUS
  928. NbfCreateAddress(
  929. IN PDEVICE_CONTEXT DeviceContext,
  930. IN PNBF_NETBIOS_ADDRESS NetworkName,
  931. OUT PTP_ADDRESS *Address
  932. )
  933. /*++
  934. Routine Description:
  935. This routine creates a transport address and associates it with
  936. the specified transport device context. The reference count in the
  937. address is automatically set to 1, and the reference count of the
  938. device context is incremented.
  939. NOTE: This routine must be called with the DeviceContext
  940. spinlock held.
  941. Arguments:
  942. DeviceContext - Pointer to the device context (which is really just
  943. the device object with its extension) to be associated with the
  944. address.
  945. NetworkName - Pointer to an NBF_NETBIOS_ADDRESS type containing the network
  946. name to be associated with this address, if any.
  947. NOTE: This has only the basic NetbiosNameType values, not the
  948. QUICK_ ones.
  949. Address - Pointer to a place where this routine will return a pointer
  950. to a transport address structure.
  951. Return Value:
  952. NTSTATUS - status of operation.
  953. --*/
  954. {
  955. PTP_ADDRESS pAddress;
  956. PLIST_ENTRY p;
  957. p = RemoveHeadList (&DeviceContext->AddressPool);
  958. if (p == &DeviceContext->AddressPool) {
  959. if ((DeviceContext->AddressMaxAllocated == 0) ||
  960. (DeviceContext->AddressAllocated < DeviceContext->AddressMaxAllocated)) {
  961. NbfAllocateAddress (DeviceContext, &pAddress);
  962. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  963. NbfPrint1 ("NBF: Allocated address at %lx\n", pAddress);
  964. }
  965. } else {
  966. NbfWriteResourceErrorLog(
  967. DeviceContext,
  968. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  969. 401,
  970. sizeof(TP_ADDRESS),
  971. ADDRESS_RESOURCE_ID);
  972. pAddress = NULL;
  973. }
  974. if (pAddress == NULL) {
  975. ++DeviceContext->AddressExhausted;
  976. PANIC ("NbfCreateAddress: Could not allocate address object!\n");
  977. return STATUS_INSUFFICIENT_RESOURCES;
  978. }
  979. } else {
  980. pAddress = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  981. }
  982. ++DeviceContext->AddressInUse;
  983. if (DeviceContext->AddressInUse > DeviceContext->AddressMaxInUse) {
  984. ++DeviceContext->AddressMaxInUse;
  985. }
  986. DeviceContext->AddressTotal += DeviceContext->AddressInUse;
  987. ++DeviceContext->AddressSamples;
  988. IF_NBFDBG (NBF_DEBUG_ADDRESS | NBF_DEBUG_UFRAMES) {
  989. NbfPrint1 ("NbfCreateAddress %lx: ", pAddress);
  990. NbfDbgShowAddr (NetworkName);
  991. }
  992. //
  993. // Initialize all of the static data for this address.
  994. //
  995. pAddress->ReferenceCount = 1;
  996. #if DBG
  997. {
  998. UINT Counter;
  999. for (Counter = 0; Counter < NUMBER_OF_AREFS; Counter++) {
  1000. pAddress->RefTypes[Counter] = 0;
  1001. }
  1002. // This reference is removed by the caller.
  1003. pAddress->RefTypes[AREF_TEMP_CREATE] = 1;
  1004. }
  1005. #endif
  1006. pAddress->Flags = ADDRESS_FLAGS_NEEDS_REG;
  1007. InitializeListHead (&pAddress->AddressFileDatabase);
  1008. pAddress->NetworkName = NetworkName;
  1009. if ((NetworkName != (PNBF_NETBIOS_ADDRESS)NULL) &&
  1010. (NetworkName->NetbiosNameType ==
  1011. TDI_ADDRESS_NETBIOS_TYPE_GROUP)) {
  1012. pAddress->Flags |= ADDRESS_FLAGS_GROUP;
  1013. }
  1014. if (NetworkName != (PNBF_NETBIOS_ADDRESS)NULL) {
  1015. ++DeviceContext->AddressCounts[NetworkName->NetbiosName[0]];
  1016. }
  1017. //
  1018. // Now link this address into the specified device context's
  1019. // address database. To do this, we need to acquire the spin lock
  1020. // on the device context.
  1021. //
  1022. InsertTailList (&DeviceContext->AddressDatabase, &pAddress->Linkage);
  1023. pAddress->Provider = DeviceContext;
  1024. NbfReferenceDeviceContext ("Create Address", DeviceContext, DCREF_ADDRESS); // count refs to the device context.
  1025. *Address = pAddress; // return the address.
  1026. return STATUS_SUCCESS; // not finished yet.
  1027. } /* NbfCreateAddress */
  1028. VOID
  1029. NbfRegisterAddress(
  1030. PTP_ADDRESS Address
  1031. )
  1032. /*++
  1033. Routine Description:
  1034. This routine starts the registration process of the transport address
  1035. specified, if it has not already been started.
  1036. Arguments:
  1037. Address - Pointer to a transport address object to begin registering
  1038. on the network.
  1039. Return Value:
  1040. NTSTATUS - status of operation.
  1041. --*/
  1042. {
  1043. KIRQL oldirql;
  1044. LARGE_INTEGER Timeout;
  1045. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1046. if (!(Address->Flags & ADDRESS_FLAGS_NEEDS_REG)) {
  1047. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1048. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1049. NbfPrint1 ("NbfRegisterAddress %lx: NEEDS_REG 0.\n", Address);
  1050. }
  1051. return;
  1052. }
  1053. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1054. NbfPrint1 ("NbfRegisterAddress %lx: registering.\n", Address);
  1055. }
  1056. Address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG;
  1057. Address->Flags |= ADDRESS_FLAGS_REGISTERING;
  1058. RtlZeroMemory (Address->UniqueResponseAddress, 6);
  1059. //
  1060. // Keep a reference on this address until the registration process
  1061. // completes or is aborted. It will be aborted in UFRAMES.C, in
  1062. // either the NAME_IN_CONFLICT or ADD_NAME_RESPONSE frame handlers.
  1063. //
  1064. NbfReferenceAddress ("start registration", Address, AREF_TIMER);
  1065. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1066. //
  1067. // Now start registration process by starting up a retransmission timer
  1068. // and begin sending ADD_NAME_QUERY NetBIOS frames.
  1069. //
  1070. // On an async line that is disconnected, we only send one packet
  1071. // with a short timeout.
  1072. //
  1073. if (Address->Provider->MacInfo.MediumAsync && !Address->Provider->MediumSpeedAccurate) {
  1074. Address->Retries = 1;
  1075. Timeout.LowPart = (ULONG)(-(ADD_NAME_QUERY_TIMEOUT / 10));
  1076. } else {
  1077. Address->Retries = Address->Provider->AddNameQueryRetries;
  1078. Timeout.LowPart = (ULONG)(-(LONG)Address->Provider->AddNameQueryTimeout);
  1079. }
  1080. Timeout.HighPart = -1;
  1081. KeSetTimer (&Address->Timer, *(PTIME)&Timeout, &Address->Dpc);
  1082. (VOID)NbfSendAddNameQuery (Address); // send first ADD_NAME_QUERY.
  1083. } /* NbfRegisterAddress */
  1084. NTSTATUS
  1085. NbfVerifyAddressObject (
  1086. IN PTP_ADDRESS_FILE AddressFile
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. This routine is called to verify that the pointer given us in a file
  1091. object is in fact a valid address file object. We also verify that the
  1092. address object pointed to by it is a valid address object, and reference
  1093. it to keep it from disappearing while we use it.
  1094. Arguments:
  1095. AddressFile - potential pointer to a TP_ADDRESS_FILE object
  1096. Return Value:
  1097. STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
  1098. --*/
  1099. {
  1100. KIRQL oldirql;
  1101. NTSTATUS status = STATUS_SUCCESS;
  1102. PTP_ADDRESS address;
  1103. //
  1104. // try to verify the address file signature. If the signature is valid,
  1105. // verify the address pointed to by it and get the address spinlock.
  1106. // check the address's state, and increment the reference count if it's
  1107. // ok to use it. Note that the only time we return an error for state is
  1108. // if the address is closing.
  1109. //
  1110. try {
  1111. if ((AddressFile != (PTP_ADDRESS_FILE)NULL) &&
  1112. (AddressFile->Size == sizeof (TP_ADDRESS_FILE)) &&
  1113. (AddressFile->Type == NBF_ADDRESSFILE_SIGNATURE) ) {
  1114. // (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) {
  1115. address = AddressFile->Address;
  1116. if ((address != (PTP_ADDRESS)NULL) &&
  1117. (address->Size == sizeof (TP_ADDRESS)) &&
  1118. (address->Type == NBF_ADDRESS_SIGNATURE) ) {
  1119. ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
  1120. if ((address->Flags & ADDRESS_FLAGS_STOPPING) == 0) {
  1121. NbfReferenceAddress ("verify", address, AREF_VERIFY);
  1122. } else {
  1123. NbfPrint1("NbfVerifyAddress: A %lx closing\n", address);
  1124. status = STATUS_INVALID_ADDRESS;
  1125. }
  1126. RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
  1127. } else {
  1128. NbfPrint1("NbfVerifyAddress: A %lx bad signature\n", address);
  1129. status = STATUS_INVALID_ADDRESS;
  1130. }
  1131. } else {
  1132. NbfPrint1("NbfVerifyAddress: AF %lx bad signature\n", AddressFile);
  1133. status = STATUS_INVALID_ADDRESS;
  1134. }
  1135. } except(EXCEPTION_EXECUTE_HANDLER) {
  1136. NbfPrint1("NbfVerifyAddress: AF %lx exception\n", address);
  1137. return GetExceptionCode();
  1138. }
  1139. return status;
  1140. }
  1141. VOID
  1142. NbfDestroyAddress(
  1143. IN PVOID Parameter
  1144. )
  1145. /*++
  1146. Routine Description:
  1147. This routine destroys a transport address and removes all references
  1148. made by it to other objects in the transport. The address structure
  1149. is returned to nonpaged system pool or our lookaside list. It is assumed
  1150. that the caller has already removed all addressfile structures associated
  1151. with this address.
  1152. The routine is called from a worker thread so that the security
  1153. descriptor can be accessed.
  1154. This worked thread is only queued by NbfDerefAddress. The reason
  1155. for this is that there may be multiple streams of execution which are
  1156. simultaneously referencing the same address object, and it should
  1157. not be deleted out from under an interested stream of execution.
  1158. Arguments:
  1159. Address - Pointer to a transport address structure to be destroyed.
  1160. Return Value:
  1161. NTSTATUS - status of operation.
  1162. --*/
  1163. {
  1164. KIRQL oldirql;
  1165. PDEVICE_CONTEXT DeviceContext;
  1166. PTP_ADDRESS Address = (PTP_ADDRESS)Parameter;
  1167. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1168. NbfPrint1 ("NbfDestroyAddress %lx:.\n", Address);
  1169. }
  1170. DeviceContext = Address->Provider;
  1171. SeDeassignSecurity (&Address->SecurityDescriptor);
  1172. //
  1173. // Delink this address from its associated device context's address
  1174. // database. To do this we must spin lock on the device context object,
  1175. // not on the address.
  1176. //
  1177. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1178. if (Address->NetworkName) {
  1179. --DeviceContext->AddressCounts[Address->NetworkName->NetbiosName[0]];
  1180. }
  1181. RemoveEntryList (&Address->Linkage);
  1182. if (Address->NetworkName != NULL) {
  1183. ExFreePool (Address->NetworkName);
  1184. Address->NetworkName = NULL;
  1185. }
  1186. //
  1187. // Now we can deallocate the transport address object.
  1188. //
  1189. DeviceContext->AddressTotal += DeviceContext->AddressInUse;
  1190. ++DeviceContext->AddressSamples;
  1191. --DeviceContext->AddressInUse;
  1192. if ((DeviceContext->AddressAllocated - DeviceContext->AddressInUse) >
  1193. DeviceContext->AddressInitAllocated) {
  1194. NbfDeallocateAddress (DeviceContext, Address);
  1195. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1196. NbfPrint1 ("NBF: Deallocated address at %lx\n", Address);
  1197. }
  1198. } else {
  1199. InsertTailList (&DeviceContext->AddressPool, &Address->Linkage);
  1200. }
  1201. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1202. NbfDereferenceDeviceContext ("Destroy Address", DeviceContext, DCREF_ADDRESS); // just housekeeping.
  1203. } /* NbfDestroyAddress */
  1204. #if DBG
  1205. VOID
  1206. NbfRefAddress(
  1207. IN PTP_ADDRESS Address
  1208. )
  1209. /*++
  1210. Routine Description:
  1211. This routine increments the reference count on a transport address.
  1212. Arguments:
  1213. Address - Pointer to a transport address object.
  1214. Return Value:
  1215. none.
  1216. --*/
  1217. {
  1218. ASSERT (Address->ReferenceCount > 0); // not perfect, but...
  1219. (VOID)InterlockedIncrement (&Address->ReferenceCount);
  1220. } /* NbfRefAddress */
  1221. #endif
  1222. VOID
  1223. NbfDerefAddress(
  1224. IN PTP_ADDRESS Address
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. This routine dereferences a transport address by decrementing the
  1229. reference count contained in the structure. If, after being
  1230. decremented, the reference count is zero, then this routine calls
  1231. NbfDestroyAddress to remove it from the system.
  1232. Arguments:
  1233. Address - Pointer to a transport address object.
  1234. Return Value:
  1235. none.
  1236. --*/
  1237. {
  1238. LONG result;
  1239. result = InterlockedDecrement (&Address->ReferenceCount);
  1240. //
  1241. // If we have deleted all references to this address, then we can
  1242. // destroy the object. It is okay to have already released the spin
  1243. // lock at this point because there is no possible way that another
  1244. // stream of execution has access to the address any longer.
  1245. //
  1246. ASSERT (result >= 0);
  1247. if (result == 0) {
  1248. ASSERT ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0);
  1249. ExInitializeWorkItem(
  1250. &Address->u.DestroyAddressQueueItem,
  1251. NbfDestroyAddress,
  1252. (PVOID)Address);
  1253. ExQueueWorkItem(&Address->u.DestroyAddressQueueItem, DelayedWorkQueue);
  1254. }
  1255. } /* NbfDerefAddress */
  1256. VOID
  1257. NbfAllocateAddressFile(
  1258. IN PDEVICE_CONTEXT DeviceContext,
  1259. OUT PTP_ADDRESS_FILE *TransportAddressFile
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. This routine allocates storage for an address file. Some
  1264. minimal initialization is done on the object.
  1265. NOTE: This routine is called with the device context spinlock
  1266. held, or at such a time as synchronization is unnecessary.
  1267. Arguments:
  1268. DeviceContext - Pointer to the device context (which is really just
  1269. the device object with its extension) to be associated with the
  1270. address.
  1271. TransportAddressFile - Pointer to a place where this routine will return
  1272. a pointer to a transport address file structure. It returns NULL if no
  1273. storage can be allocated.
  1274. Return Value:
  1275. None.
  1276. --*/
  1277. {
  1278. PTP_ADDRESS_FILE AddressFile;
  1279. if ((DeviceContext->MemoryLimit != 0) &&
  1280. ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS_FILE)) >
  1281. DeviceContext->MemoryLimit)) {
  1282. PANIC("NBF: Could not allocate address file: limit\n");
  1283. NbfWriteResourceErrorLog(
  1284. DeviceContext,
  1285. EVENT_TRANSPORT_RESOURCE_LIMIT,
  1286. 102,
  1287. sizeof(TP_ADDRESS_FILE),
  1288. ADDRESS_FILE_RESOURCE_ID);
  1289. *TransportAddressFile = NULL;
  1290. return;
  1291. }
  1292. AddressFile = (PTP_ADDRESS_FILE)ExAllocatePoolWithTag (
  1293. NonPagedPool,
  1294. sizeof (TP_ADDRESS_FILE),
  1295. NBF_MEM_TAG_TP_ADDRESS_FILE);
  1296. if (AddressFile == NULL) {
  1297. PANIC("NBF: Could not allocate address file: no pool\n");
  1298. NbfWriteResourceErrorLog(
  1299. DeviceContext,
  1300. EVENT_TRANSPORT_RESOURCE_POOL,
  1301. 202,
  1302. sizeof(TP_ADDRESS_FILE),
  1303. ADDRESS_FILE_RESOURCE_ID);
  1304. *TransportAddressFile = NULL;
  1305. return;
  1306. }
  1307. RtlZeroMemory (AddressFile, sizeof(TP_ADDRESS_FILE));
  1308. DeviceContext->MemoryUsage += sizeof(TP_ADDRESS_FILE);
  1309. ++DeviceContext->AddressFileAllocated;
  1310. AddressFile->Type = NBF_ADDRESSFILE_SIGNATURE;
  1311. AddressFile->Size = sizeof (TP_ADDRESS_FILE);
  1312. InitializeListHead (&AddressFile->ReceiveDatagramQueue);
  1313. InitializeListHead (&AddressFile->ConnectionDatabase);
  1314. *TransportAddressFile = AddressFile;
  1315. } /* NbfAllocateAddressFile */
  1316. VOID
  1317. NbfDeallocateAddressFile(
  1318. IN PDEVICE_CONTEXT DeviceContext,
  1319. IN PTP_ADDRESS_FILE TransportAddressFile
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. This routine frees storage for an address file.
  1324. NOTE: This routine is called with the device context spinlock
  1325. held, or at such a time as synchronization is unnecessary.
  1326. Arguments:
  1327. DeviceContext - Pointer to the device context (which is really just
  1328. the device object with its extension) to be associated with the
  1329. address.
  1330. TransportAddressFile - Pointer to a transport address file structure.
  1331. Return Value:
  1332. None.
  1333. --*/
  1334. {
  1335. ExFreePool (TransportAddressFile);
  1336. --DeviceContext->AddressFileAllocated;
  1337. DeviceContext->MemoryUsage -= sizeof(TP_ADDRESS_FILE);
  1338. } /* NbfDeallocateAddressFile */
  1339. NTSTATUS
  1340. NbfCreateAddressFile(
  1341. IN PDEVICE_CONTEXT DeviceContext,
  1342. OUT PTP_ADDRESS_FILE * AddressFile
  1343. )
  1344. /*++
  1345. Routine Description:
  1346. This routine creates an address file from the pool of ther
  1347. specified device context. The reference count in the
  1348. address is automatically set to 1.
  1349. Arguments:
  1350. DeviceContext - Pointer to the device context (which is really just
  1351. the device object with its extension) to be associated with the
  1352. address.
  1353. AddressFile - Pointer to a place where this routine will return a pointer
  1354. to a transport address file structure.
  1355. Return Value:
  1356. NTSTATUS - status of operation.
  1357. --*/
  1358. {
  1359. KIRQL oldirql;
  1360. PLIST_ENTRY p;
  1361. PTP_ADDRESS_FILE addressFile;
  1362. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1363. p = RemoveHeadList (&DeviceContext->AddressFilePool);
  1364. if (p == &DeviceContext->AddressFilePool) {
  1365. if ((DeviceContext->AddressFileMaxAllocated == 0) ||
  1366. (DeviceContext->AddressFileAllocated < DeviceContext->AddressFileMaxAllocated)) {
  1367. NbfAllocateAddressFile (DeviceContext, &addressFile);
  1368. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1369. NbfPrint1 ("NBF: Allocated address file at %lx\n", addressFile);
  1370. }
  1371. } else {
  1372. NbfWriteResourceErrorLog(
  1373. DeviceContext,
  1374. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  1375. 402,
  1376. sizeof(TP_ADDRESS_FILE),
  1377. ADDRESS_FILE_RESOURCE_ID);
  1378. addressFile = NULL;
  1379. }
  1380. if (addressFile == NULL) {
  1381. ++DeviceContext->AddressFileExhausted;
  1382. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1383. PANIC ("NbfCreateAddressFile: Could not allocate address file object!\n");
  1384. return STATUS_INSUFFICIENT_RESOURCES;
  1385. }
  1386. } else {
  1387. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  1388. }
  1389. ++DeviceContext->AddressFileInUse;
  1390. if (DeviceContext->AddressFileInUse > DeviceContext->AddressFileMaxInUse) {
  1391. ++DeviceContext->AddressFileMaxInUse;
  1392. }
  1393. DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse;
  1394. ++DeviceContext->AddressFileSamples;
  1395. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1396. InitializeListHead (&addressFile->ConnectionDatabase);
  1397. addressFile->Address = NULL;
  1398. addressFile->FileObject = NULL;
  1399. addressFile->Provider = DeviceContext;
  1400. addressFile->State = ADDRESSFILE_STATE_OPENING;
  1401. addressFile->ConnectIndicationInProgress = FALSE;
  1402. addressFile->ReferenceCount = 1;
  1403. addressFile->CloseIrp = (PIRP)NULL;
  1404. //
  1405. // Initialize the request handlers.
  1406. //
  1407. addressFile->RegisteredConnectionHandler = FALSE;
  1408. addressFile->ConnectionHandler = TdiDefaultConnectHandler;
  1409. addressFile->ConnectionHandlerContext = NULL;
  1410. addressFile->RegisteredDisconnectHandler = FALSE;
  1411. addressFile->DisconnectHandler = TdiDefaultDisconnectHandler;
  1412. addressFile->DisconnectHandlerContext = NULL;
  1413. addressFile->RegisteredReceiveHandler = FALSE;
  1414. addressFile->ReceiveHandler = TdiDefaultReceiveHandler;
  1415. addressFile->ReceiveHandlerContext = NULL;
  1416. addressFile->RegisteredReceiveDatagramHandler = FALSE;
  1417. addressFile->ReceiveDatagramHandler = TdiDefaultRcvDatagramHandler;
  1418. addressFile->ReceiveDatagramHandlerContext = NULL;
  1419. addressFile->RegisteredExpeditedDataHandler = FALSE;
  1420. addressFile->ExpeditedDataHandler = TdiDefaultRcvExpeditedHandler;
  1421. addressFile->ExpeditedDataHandlerContext = NULL;
  1422. addressFile->RegisteredErrorHandler = FALSE;
  1423. addressFile->ErrorHandler = TdiDefaultErrorHandler;
  1424. addressFile->ErrorHandlerContext = NULL;
  1425. *AddressFile = addressFile;
  1426. return STATUS_SUCCESS;
  1427. } /* NbfCreateAddress */
  1428. NTSTATUS
  1429. NbfDestroyAddressFile(
  1430. IN PTP_ADDRESS_FILE AddressFile
  1431. )
  1432. /*++
  1433. Routine Description:
  1434. This routine destroys an address file and removes all references
  1435. made by it to other objects in the transport.
  1436. This routine is only called by NbfDereferenceAddressFile. The reason
  1437. for this is that there may be multiple streams of execution which are
  1438. simultaneously referencing the same address file object, and it should
  1439. not be deleted out from under an interested stream of execution.
  1440. Arguments:
  1441. AddressFile Pointer to a transport address file structure to be destroyed.
  1442. Return Value:
  1443. NTSTATUS - status of operation.
  1444. --*/
  1445. {
  1446. KIRQL oldirql, oldirql1;
  1447. PTP_ADDRESS address;
  1448. PDEVICE_CONTEXT DeviceContext;
  1449. PIRP CloseIrp;
  1450. address = AddressFile->Address;
  1451. DeviceContext = AddressFile->Provider;
  1452. if (address) {
  1453. //
  1454. // This addressfile was associated with an address.
  1455. //
  1456. ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
  1457. //
  1458. // remove this addressfile from the address list and disassociate it from
  1459. // the file handle.
  1460. //
  1461. RemoveEntryList (&AddressFile->Linkage);
  1462. InitializeListHead (&AddressFile->Linkage);
  1463. if (address->AddressFileDatabase.Flink == &address->AddressFileDatabase) {
  1464. //
  1465. // This is the last open of this address, it will close
  1466. // due to normal dereferencing but we have to set the
  1467. // CLOSING flag too to stop further references.
  1468. //
  1469. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1);
  1470. address->Flags |= ADDRESS_FLAGS_STOPPING;
  1471. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1);
  1472. }
  1473. AddressFile->Address = NULL;
  1474. AddressFile->FileObject->FsContext = NULL;
  1475. AddressFile->FileObject->FsContext2 = NULL;
  1476. RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
  1477. //
  1478. // We will already have been removed from the ShareAccess
  1479. // of the owning address.
  1480. //
  1481. //
  1482. // Now dereference the owning address.
  1483. //
  1484. NbfDereferenceAddress ("Close", address, AREF_OPEN); // remove the creation hold
  1485. }
  1486. //
  1487. // Save this for later completion.
  1488. //
  1489. CloseIrp = AddressFile->CloseIrp;
  1490. //
  1491. // return the addressFile to the pool of address files
  1492. //
  1493. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1494. DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse;
  1495. ++DeviceContext->AddressFileSamples;
  1496. --DeviceContext->AddressFileInUse;
  1497. if ((DeviceContext->AddressFileAllocated - DeviceContext->AddressFileInUse) >
  1498. DeviceContext->AddressFileInitAllocated) {
  1499. NbfDeallocateAddressFile (DeviceContext, AddressFile);
  1500. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  1501. NbfPrint1 ("NBF: Deallocated address file at %lx\n", AddressFile);
  1502. }
  1503. } else {
  1504. InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage);
  1505. }
  1506. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1507. if (CloseIrp != (PIRP)NULL) {
  1508. CloseIrp->IoStatus.Information = 0;
  1509. CloseIrp->IoStatus.Status = STATUS_SUCCESS;
  1510. IoCompleteRequest (CloseIrp, IO_NETWORK_INCREMENT);
  1511. }
  1512. return STATUS_SUCCESS;
  1513. } /* NbfDestroyAddressFile */
  1514. VOID
  1515. NbfReferenceAddressFile(
  1516. IN PTP_ADDRESS_FILE AddressFile
  1517. )
  1518. /*++
  1519. Routine Description:
  1520. This routine increments the reference count on an address file.
  1521. Arguments:
  1522. AddressFile - Pointer to a transport address file object.
  1523. Return Value:
  1524. none.
  1525. --*/
  1526. {
  1527. ASSERT (AddressFile->ReferenceCount > 0); // not perfect, but...
  1528. (VOID)InterlockedIncrement (&AddressFile->ReferenceCount);
  1529. } /* NbfReferenceAddressFile */
  1530. VOID
  1531. NbfDereferenceAddressFile(
  1532. IN PTP_ADDRESS_FILE AddressFile
  1533. )
  1534. /*++
  1535. Routine Description:
  1536. This routine dereferences an address file by decrementing the
  1537. reference count contained in the structure. If, after being
  1538. decremented, the reference count is zero, then this routine calls
  1539. NbfDestroyAddressFile to remove it from the system.
  1540. Arguments:
  1541. AddressFile - Pointer to a transport address file object.
  1542. Return Value:
  1543. none.
  1544. --*/
  1545. {
  1546. LONG result;
  1547. result = InterlockedDecrement (&AddressFile->ReferenceCount);
  1548. //
  1549. // If we have deleted all references to this address file, then we can
  1550. // destroy the object. It is okay to have already released the spin
  1551. // lock at this point because there is no possible way that another
  1552. // stream of execution has access to the address any longer.
  1553. //
  1554. ASSERT (result >= 0);
  1555. if (result == 0) {
  1556. NbfDestroyAddressFile (AddressFile);
  1557. }
  1558. } /* NbfDerefAddressFile */
  1559. PTP_ADDRESS
  1560. NbfLookupAddress(
  1561. IN PDEVICE_CONTEXT DeviceContext,
  1562. IN PNBF_NETBIOS_ADDRESS NetworkName
  1563. )
  1564. /*++
  1565. Routine Description:
  1566. This routine scans the transport addresses defined for the given
  1567. device context and compares them with the specified NETWORK
  1568. NAME values. If an exact match is found, then a pointer to the
  1569. TP_ADDRESS object is returned, and as a side effect, the reference
  1570. count to the address object is incremented. If the address is not
  1571. found, then NULL is returned.
  1572. NOTE: This routine must be called with the DeviceContext
  1573. spinlock held.
  1574. Arguments:
  1575. DeviceContext - Pointer to the device object and its extension.
  1576. NetworkName - Pointer to an NBF_NETBIOS_ADDRESS structure containing the
  1577. network name.
  1578. Return Value:
  1579. Pointer to the TP_ADDRESS object found, or NULL if not found.
  1580. --*/
  1581. {
  1582. PTP_ADDRESS address;
  1583. PLIST_ENTRY p;
  1584. ULONG i;
  1585. p = DeviceContext->AddressDatabase.Flink;
  1586. for (p = DeviceContext->AddressDatabase.Flink;
  1587. p != &DeviceContext->AddressDatabase;
  1588. p = p->Flink) {
  1589. address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  1590. if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
  1591. continue;
  1592. }
  1593. //
  1594. // If the network name is specified and the network names don't match,
  1595. // then the addresses don't match.
  1596. //
  1597. i = NETBIOS_NAME_LENGTH; // length of a Netbios name
  1598. if (address->NetworkName != NULL) {
  1599. if (NetworkName != NULL) {
  1600. if (!RtlEqualMemory (
  1601. address->NetworkName->NetbiosName,
  1602. NetworkName->NetbiosName,
  1603. i)) {
  1604. continue;
  1605. }
  1606. } else {
  1607. continue;
  1608. }
  1609. } else {
  1610. if (NetworkName != NULL) {
  1611. continue;
  1612. }
  1613. }
  1614. //
  1615. // We found the match. Bump the reference count on the address, and
  1616. // return a pointer to the address object for the caller to use.
  1617. //
  1618. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1619. NbfPrint2 ("NbfLookupAddress DC %lx: found %lx ", DeviceContext, address);
  1620. NbfDbgShowAddr (NetworkName);
  1621. }
  1622. NbfReferenceAddress ("lookup", address, AREF_LOOKUP);
  1623. return address;
  1624. } /* for */
  1625. //
  1626. // The specified address was not found.
  1627. //
  1628. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1629. NbfPrint1 ("NbfLookupAddress DC %lx: did not find ", address);
  1630. NbfDbgShowAddr (NetworkName);
  1631. }
  1632. return NULL;
  1633. } /* NbfLookupAddress */
  1634. PTP_CONNECTION
  1635. NbfLookupRemoteName(
  1636. IN PTP_ADDRESS Address,
  1637. IN PUCHAR RemoteName,
  1638. IN UCHAR RemoteSessionNumber
  1639. )
  1640. /*++
  1641. Routine Description:
  1642. This routine scans the connections associated with the
  1643. given address, and determines if there is an connection
  1644. associated with the specific remote address and session
  1645. number which is becoming active. This is used
  1646. in determining whether name queries should be processed,
  1647. or ignored as duplicates.
  1648. Arguments:
  1649. Address - Pointer to the address object.
  1650. RemoteName - The 16-character Netbios name of the remote.
  1651. RemoteSessionNumber - The session number assigned to this
  1652. connection by the remote.
  1653. Return Value:
  1654. The connection if one is found, NULL otherwise.
  1655. --*/
  1656. {
  1657. KIRQL oldirql, oldirql1;
  1658. PLIST_ENTRY p;
  1659. PTP_CONNECTION connection;
  1660. BOOLEAN Found = FALSE;
  1661. //
  1662. // Hold the spinlock so the connection database doesn't
  1663. // change.
  1664. //
  1665. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1666. for (p=Address->ConnectionDatabase.Flink;
  1667. p != &Address->ConnectionDatabase;
  1668. p=p->Flink) {
  1669. connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressList);
  1670. try {
  1671. ACQUIRE_C_SPIN_LOCK (&connection->SpinLock, &oldirql1);
  1672. if (((connection->Flags2 & CONNECTION_FLAGS2_REMOTE_VALID) != 0) &&
  1673. ((connection->Flags & CONNECTION_FLAGS_READY) == 0)) {
  1674. RELEASE_C_SPIN_LOCK (&connection->SpinLock, oldirql1);
  1675. //
  1676. // If the remote names match, and the connection's RSN is
  1677. // the same (or zero, which is a temporary condition where
  1678. // we should err on the side of caution), then return the
  1679. // connection, which will cause the NAME_QUERY to be ignored.
  1680. //
  1681. if ((RtlEqualMemory(RemoteName, connection->RemoteName, NETBIOS_NAME_LENGTH)) &&
  1682. ((connection->Rsn == RemoteSessionNumber) || (connection->Rsn == 0))) {
  1683. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1684. NbfReferenceConnection ("Lookup found", connection, CREF_LISTENING);
  1685. Found = TRUE;
  1686. }
  1687. } else {
  1688. RELEASE_C_SPIN_LOCK (&connection->SpinLock, oldirql1);
  1689. }
  1690. } except(EXCEPTION_EXECUTE_HANDLER) {
  1691. DbgPrint ("NBF: Got exception in NbfLookupRemoteName\n");
  1692. DbgBreakPoint();
  1693. RELEASE_C_SPIN_LOCK (&connection->SpinLock, oldirql1);
  1694. return (PTP_CONNECTION)NULL;
  1695. }
  1696. if (Found) {
  1697. return connection;
  1698. }
  1699. }
  1700. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1701. return (PTP_CONNECTION)NULL;
  1702. }
  1703. BOOLEAN
  1704. NbfMatchNetbiosAddress(
  1705. IN PTP_ADDRESS Address,
  1706. IN UCHAR NameType,
  1707. IN PUCHAR NetBIOSName
  1708. )
  1709. /*++
  1710. Routine Description:
  1711. This routine is called to compare the addressing information in a
  1712. TP_ADDRESS object with the 16-byte NetBIOS name in a frame header.
  1713. If they match, then this routine returns TRUE, else it returns FALSE.
  1714. Arguments:
  1715. Address - Pointer to a TP_ADDRESS object.
  1716. NameType - One of NETBIOS_NAME_TYPE_GROUP, NETBIOS_NAME_TYPE_UNIQUE,
  1717. or NETBIOS_NAME_TYPE_EITHER. Controls what type we are matching
  1718. on, if it matters.
  1719. NetBIOSName - Pointer to a 16-byte character string (non-terminated),
  1720. or NULL if this is a received broadcast address.
  1721. Return Value:
  1722. BOOLEAN, TRUE if match, FALSE if not.
  1723. --*/
  1724. {
  1725. PULONG AddressNamePointer;
  1726. ULONG UNALIGNED * NetbiosNamePointer;
  1727. //
  1728. // If this is address is the Netbios broadcast address, the comparison
  1729. // succeeds only if the passed in address is also NULL.
  1730. //
  1731. if (Address->NetworkName == NULL) {
  1732. if (NetBIOSName == NULL) {
  1733. return TRUE;
  1734. } else {
  1735. return FALSE;
  1736. }
  1737. } else if (NetBIOSName == NULL) {
  1738. return FALSE;
  1739. }
  1740. //
  1741. // Do a quick check of the first character in the names.
  1742. //
  1743. if (Address->NetworkName->NetbiosName[0] != NetBIOSName[0]) {
  1744. return FALSE;
  1745. }
  1746. //
  1747. // If name type is important and it doesn't match
  1748. // this address' type, fail.
  1749. //
  1750. if (NameType != NETBIOS_NAME_TYPE_EITHER) {
  1751. if (Address->NetworkName->NetbiosNameType != (USHORT)NameType) {
  1752. return FALSE;
  1753. }
  1754. }
  1755. IF_NBFDBG (NBF_DEBUG_DATAGRAMS) {
  1756. NbfPrint2 ("MatchNetbiosAddress %lx: compare %.16s to ", Address, NetBIOSName);
  1757. NbfDbgShowAddr (Address->NetworkName);
  1758. }
  1759. //
  1760. // Now compare the 16-character Netbios names as ULONGs
  1761. // for speed. We know the one stored in the address
  1762. // structure is aligned.
  1763. //
  1764. AddressNamePointer = (PULONG)(Address->NetworkName->NetbiosName);
  1765. NetbiosNamePointer = (ULONG UNALIGNED *)NetBIOSName;
  1766. if ((AddressNamePointer[0] == NetbiosNamePointer[0]) &&
  1767. (AddressNamePointer[1] == NetbiosNamePointer[1]) &&
  1768. (AddressNamePointer[2] == NetbiosNamePointer[2]) &&
  1769. (AddressNamePointer[3] == NetbiosNamePointer[3])) {
  1770. return TRUE;
  1771. } else {
  1772. return FALSE;
  1773. }
  1774. } /* NbfMatchNetbiosAddress */
  1775. VOID
  1776. NbfStopAddress(
  1777. IN PTP_ADDRESS Address
  1778. )
  1779. /*++
  1780. Routine Description:
  1781. This routine is called to terminate all activity on an address and
  1782. destroy the object. This is done in a graceful manner; i.e., all
  1783. outstanding addressfiles are removed from the addressfile database, and
  1784. all their activities are shut down.
  1785. Arguments:
  1786. Address - Pointer to a TP_ADDRESS object.
  1787. Return Value:
  1788. none.
  1789. --*/
  1790. {
  1791. KIRQL oldirql, oldirql1;
  1792. PTP_ADDRESS_FILE addressFile;
  1793. PLIST_ENTRY p;
  1794. PDEVICE_CONTEXT DeviceContext;
  1795. DeviceContext = Address->Provider;
  1796. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1797. //
  1798. // If we're already stopping this address, then don't try to do it again.
  1799. //
  1800. if (!(Address->Flags & ADDRESS_FLAGS_STOPPING)) {
  1801. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1802. NbfPrint1 ("NbfStopAddress %lx: stopping\n", Address);
  1803. }
  1804. NbfReferenceAddress ("Stopping", Address, AREF_TEMP_STOP);
  1805. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1);
  1806. Address->Flags |= ADDRESS_FLAGS_STOPPING;
  1807. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1);
  1808. //
  1809. // Run down all addressfiles on this address. This
  1810. // will leave the address with no references
  1811. // potentially, but we don't need a temp one
  1812. // because every place that calls NbfStopAddress
  1813. // already has a temp reference.
  1814. //
  1815. while (!IsListEmpty (&Address->AddressFileDatabase)) {
  1816. p = RemoveHeadList (&Address->AddressFileDatabase);
  1817. addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
  1818. addressFile->Address = NULL;
  1819. #if 0
  1820. addressFile->FileObject->FsContext = NULL;
  1821. addressFile->FileObject->FsContext2 = NULL;
  1822. #endif
  1823. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1824. //
  1825. // Run-down this addressFile without the lock on.
  1826. // We don't care about removing ourselves from
  1827. // the address' ShareAccess because we are
  1828. // tearing it down.
  1829. //
  1830. NbfStopAddressFile (addressFile, Address);
  1831. //
  1832. // return the addressFile to the pool of address files
  1833. //
  1834. NbfDereferenceAddressFile (addressFile);
  1835. NbfDereferenceAddress ("stop address", Address, AREF_OPEN);
  1836. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1837. }
  1838. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1839. NbfDereferenceAddress ("Stopping", Address, AREF_TEMP_STOP);
  1840. } else {
  1841. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1842. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1843. NbfPrint1 ("NbfStopAddress %lx: already stopping\n", Address);
  1844. }
  1845. }
  1846. } /* NbfStopAddress */
  1847. NTSTATUS
  1848. NbfStopAddressFile(
  1849. IN PTP_ADDRESS_FILE AddressFile,
  1850. IN PTP_ADDRESS Address
  1851. )
  1852. /*++
  1853. Routine Description:
  1854. This routine is called to terminate all activity on an AddressFile and
  1855. destroy the object. We remove every connection and datagram associated
  1856. with this addressfile from the address database and terminate their
  1857. activity. Then, if there are no other outstanding addressfiles open on
  1858. this address, the address will go away.
  1859. Arguments:
  1860. AddressFile - pointer to the addressFile to be stopped
  1861. Address - the owning address for this addressFile (we do not depend upon
  1862. the pointer in the addressFile because we want this routine to be safe)
  1863. Return Value:
  1864. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not
  1865. point to a real address.
  1866. --*/
  1867. {
  1868. KIRQL oldirql, oldirql1;
  1869. LIST_ENTRY localIrpList;
  1870. PLIST_ENTRY p, pFlink;
  1871. PIRP irp;
  1872. PTP_CONNECTION connection;
  1873. ULONG fStopping;
  1874. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1875. if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) {
  1876. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1877. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  1878. NbfPrint1 ("NbfStopAddressFile %lx: already closing.\n", AddressFile);
  1879. }
  1880. return STATUS_SUCCESS;
  1881. }
  1882. IF_NBFDBG (NBF_DEBUG_ADDRESS | NBF_DEBUG_PNP) {
  1883. NbfPrint1 ("NbfStopAddressFile %lx: closing.\n", AddressFile);
  1884. }
  1885. AddressFile->State = ADDRESSFILE_STATE_CLOSING;
  1886. InitializeListHead (&localIrpList);
  1887. //
  1888. // Run down all connections on this addressfile, and
  1889. // preform the equivalent of NbfDestroyAssociation
  1890. // on them.
  1891. //
  1892. while (!IsListEmpty (&AddressFile->ConnectionDatabase)) {
  1893. p = RemoveHeadList (&AddressFile->ConnectionDatabase);
  1894. connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressFileList);
  1895. ACQUIRE_C_SPIN_LOCK (&connection->SpinLock, &oldirql1);
  1896. if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) == 0) {
  1897. //
  1898. // It is in the process of being disassociated already.
  1899. //
  1900. RELEASE_C_SPIN_LOCK (&connection->SpinLock, oldirql1);
  1901. continue;
  1902. }
  1903. connection->Flags2 &= ~CONNECTION_FLAGS2_ASSOCIATED;
  1904. connection->Flags2 |= CONNECTION_FLAGS2_DESTROY; // Is this needed?
  1905. RemoveEntryList (&connection->AddressList);
  1906. InitializeListHead (&connection->AddressList);
  1907. InitializeListHead (&connection->AddressFileList);
  1908. connection->AddressFile = NULL;
  1909. fStopping = connection->Flags2 & CONNECTION_FLAGS2_STOPPING;
  1910. #if _DBG_
  1911. DbgPrint("conn = %p, Flags2 = %08x, fStopping = %08x\n",
  1912. connection,
  1913. connection->Flags2,
  1914. fStopping);
  1915. #endif
  1916. if (!fStopping) {
  1917. #if _DBG_
  1918. DbgPrint("Refing BEG\n");
  1919. #endif
  1920. NbfReferenceConnection ("Close AddressFile", connection, CREF_STOP_ADDRESS);
  1921. #if _DBG_
  1922. DbgPrint("Refing END\n");
  1923. #endif
  1924. }
  1925. RELEASE_C_SPIN_LOCK (&connection->SpinLock, oldirql1);
  1926. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  1927. #if DBG
  1928. if (NbfDisconnectDebug) {
  1929. STRING remoteName, localName;
  1930. remoteName.Length = NETBIOS_NAME_LENGTH - 1;
  1931. remoteName.Buffer = connection->RemoteName;
  1932. localName.Length = NETBIOS_NAME_LENGTH - 1;
  1933. localName.Buffer = AddressFile->Address->NetworkName->NetbiosName;
  1934. NbfPrint2( "TpStopEndpoint stopping connection to %S from %S\n",
  1935. &remoteName, &localName );
  1936. }
  1937. #endif
  1938. if (!fStopping) {
  1939. #if _DBG_
  1940. DbgPrint("Stopping BEG\n");
  1941. #endif
  1942. KeRaiseIrql (DISPATCH_LEVEL, &oldirql1);
  1943. NbfStopConnection (connection, STATUS_LOCAL_DISCONNECT);
  1944. KeLowerIrql (oldirql1);
  1945. #if _DBG_
  1946. DbgPrint("Stopping END\n");
  1947. DbgPrint("Derefing BEG\n");
  1948. #endif
  1949. NbfDereferenceConnection ("Close AddressFile", connection, CREF_STOP_ADDRESS);
  1950. #if _DBG_
  1951. DbgPrint("Derefing END\n");
  1952. #endif
  1953. }
  1954. NbfDereferenceAddress ("Destroy association", Address, AREF_CONNECTION);
  1955. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  1956. }
  1957. //
  1958. // now remove all of the datagrams owned by this addressfile
  1959. //
  1960. //
  1961. // If the address has a datagram send in progress, skip the
  1962. // first one, it will complete when the NdisSend completes.
  1963. //
  1964. p = Address->SendDatagramQueue.Flink;
  1965. if (Address->Flags & ADDRESS_FLAGS_SEND_IN_PROGRESS) {
  1966. ASSERT (p != &Address->SendDatagramQueue);
  1967. p = p->Flink;
  1968. }
  1969. for ( ;
  1970. p != &Address->SendDatagramQueue;
  1971. p = pFlink ) {
  1972. pFlink = p->Flink;
  1973. irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  1974. if (IoGetCurrentIrpStackLocation(irp)->FileObject->FsContext == AddressFile) {
  1975. RemoveEntryList (p);
  1976. InitializeListHead (p);
  1977. InsertTailList (&localIrpList, p);
  1978. }
  1979. }
  1980. for (p = AddressFile->ReceiveDatagramQueue.Flink;
  1981. p != &AddressFile->ReceiveDatagramQueue;
  1982. p = pFlink ) {
  1983. pFlink = p->Flink;
  1984. RemoveEntryList (p);
  1985. InitializeListHead (p);
  1986. InsertTailList (&localIrpList, p);
  1987. }
  1988. //
  1989. // and finally, signal failure if the address file was waiting for a
  1990. // registration to complete (Irp is set to NULL when this succeeds).
  1991. //
  1992. if (AddressFile->Irp != NULL) {
  1993. PIRP irp=AddressFile->Irp;
  1994. #if DBG
  1995. if ((Address->Flags & ADDRESS_FLAGS_DUPLICATE_NAME) == 0) {
  1996. DbgPrint ("NBF: AddressFile %lx closed while opening!!\n", AddressFile);
  1997. DbgBreakPoint();
  1998. }
  1999. #endif
  2000. AddressFile->Irp = NULL;
  2001. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  2002. irp->IoStatus.Information = 0;
  2003. irp->IoStatus.Status = STATUS_DUPLICATE_NAME;
  2004. LEAVE_NBF;
  2005. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  2006. ENTER_NBF;
  2007. } else {
  2008. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  2009. }
  2010. //
  2011. // cancel all the datagrams on this address file
  2012. //
  2013. while (!IsListEmpty (&localIrpList)) {
  2014. KIRQL cancelIrql;
  2015. p = RemoveHeadList (&localIrpList);
  2016. irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  2017. IoAcquireCancelSpinLock(&cancelIrql);
  2018. IoSetCancelRoutine(irp, NULL);
  2019. IoReleaseCancelSpinLock(cancelIrql);
  2020. irp->IoStatus.Information = 0;
  2021. irp->IoStatus.Status = STATUS_NETWORK_NAME_DELETED;
  2022. IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
  2023. NbfDereferenceAddress ("Datagram aborted", Address, AREF_REQUEST);
  2024. }
  2025. return STATUS_SUCCESS;
  2026. } /* NbfStopAddressFile */
  2027. NTSTATUS
  2028. NbfCloseAddress(
  2029. IN PDEVICE_OBJECT DeviceObject,
  2030. IN PIRP Irp,
  2031. IN PIO_STACK_LOCATION IrpSp
  2032. )
  2033. /*++
  2034. Routine Description:
  2035. This routine is called to close the addressfile pointed to by a file
  2036. object. If there is any activity to be run down, we will run it down
  2037. before we terminate the addressfile. We remove every connection and
  2038. datagram associated with this addressfile from the address database
  2039. and terminate their activity. Then, if there are no other outstanding
  2040. addressfiles open on this address, the address will go away.
  2041. Arguments:
  2042. Irp - the Irp Address - Pointer to a TP_ADDRESS object.
  2043. Return Value:
  2044. STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not
  2045. point to a real address.
  2046. --*/
  2047. {
  2048. PTP_ADDRESS address;
  2049. PTP_ADDRESS_FILE addressFile;
  2050. addressFile = IrpSp->FileObject->FsContext;
  2051. IF_NBFDBG (NBF_DEBUG_ADDRESS | NBF_DEBUG_PNP) {
  2052. NbfPrint1 ("NbfCloseAddress AF %lx:\n", addressFile);
  2053. }
  2054. addressFile->CloseIrp = Irp;
  2055. //
  2056. // We assume that addressFile has already been verified
  2057. // at this point.
  2058. //
  2059. address = addressFile->Address;
  2060. ASSERT (address);
  2061. //
  2062. // Remove us from the access info for this address.
  2063. //
  2064. ACQUIRE_RESOURCE_EXCLUSIVE (&addressFile->Provider->AddressResource, TRUE);
  2065. IoRemoveShareAccess (addressFile->FileObject, &address->u.ShareAccess);
  2066. RELEASE_RESOURCE (&addressFile->Provider->AddressResource);
  2067. NbfStopAddressFile (addressFile, address);
  2068. NbfDereferenceAddressFile (addressFile);
  2069. //
  2070. // This removes a reference added by our caller.
  2071. //
  2072. NbfDereferenceAddress ("IRP_MJ_CLOSE", address, AREF_VERIFY);
  2073. return STATUS_PENDING;
  2074. } /* NbfCloseAddress */
  2075. NTSTATUS
  2076. NbfSendDatagramsOnAddress(
  2077. PTP_ADDRESS Address
  2078. )
  2079. /*++
  2080. Routine Description:
  2081. This routine attempts to acquire a hold on the SendDatagramQueue of
  2082. the specified address, prepare the next datagram for shipment, and
  2083. call NbfSendUIMdlFrame to actually do the work. When NbfSendUIMdlFrame
  2084. is finished, it will cause an I/O completion routine in UFRAMES.C to
  2085. be called, at which time this routine is called again to handle the
  2086. next datagram in the pipeline.
  2087. NOTE: This routine must be called at a point where the address
  2088. has another reference that will keep it around.
  2089. Arguments:
  2090. Address - a pointer to the address object to send the datagram on.
  2091. Return Value:
  2092. NTSTATUS - status of operation.
  2093. --*/
  2094. {
  2095. KIRQL oldirql;
  2096. PLIST_ENTRY p;
  2097. PIRP Irp;
  2098. TDI_ADDRESS_NETBIOS * remoteAddress;
  2099. PIO_STACK_LOCATION irpSp;
  2100. PDEVICE_CONTEXT DeviceContext;
  2101. PUCHAR SingleSR;
  2102. UINT SingleSRLength;
  2103. UINT HeaderLength;
  2104. PUCHAR LocalName;
  2105. IF_NBFDBG (NBF_DEBUG_ADDRESS) {
  2106. NbfPrint1 ("NbfSendDatagramsOnAddress %lx:\n", Address);
  2107. }
  2108. DeviceContext = Address->Provider;
  2109. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  2110. if (!(Address->Flags & ADDRESS_FLAGS_SEND_IN_PROGRESS)) {
  2111. //
  2112. // If the queue is empty, don't do anything.
  2113. //
  2114. if (IsListEmpty (&Address->SendDatagramQueue)) {
  2115. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  2116. return STATUS_SUCCESS;
  2117. }
  2118. //
  2119. // Mark the address's send datagram queue as held so that the
  2120. // MDL and NBF header will not be used for two requests at the
  2121. // same time.
  2122. //
  2123. Address->Flags |= ADDRESS_FLAGS_SEND_IN_PROGRESS;
  2124. //
  2125. // We own the hold, and we've released the spinlock. So pick off the
  2126. // next datagram to be sent, and ship it.
  2127. //
  2128. p = Address->SendDatagramQueue.Flink;
  2129. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  2130. Irp = CONTAINING_RECORD (p, IRP, Tail.Overlay.ListEntry);
  2131. //
  2132. // If there is no remote Address specified (the Address specified has
  2133. // length 0), this is a broadcast datagram. If anything is specified, it
  2134. // will be used as a netbios address.
  2135. //
  2136. irpSp = IoGetCurrentIrpStackLocation (Irp);
  2137. remoteAddress = NbfParseTdiAddress (
  2138. ((PTDI_REQUEST_KERNEL_SENDDG)(&irpSp->Parameters))->
  2139. SendDatagramInformation->RemoteAddress,
  2140. TRUE);
  2141. ASSERT (remoteAddress != NULL);
  2142. //
  2143. // Build the MAC header. DATAGRAM frames go out as
  2144. // single-route source routing.
  2145. //
  2146. MacReturnSingleRouteSR(
  2147. &DeviceContext->MacInfo,
  2148. &SingleSR,
  2149. &SingleSRLength);
  2150. MacConstructHeader (
  2151. &DeviceContext->MacInfo,
  2152. Address->UIFrame->Header,
  2153. DeviceContext->NetBIOSAddress.Address,
  2154. DeviceContext->LocalAddress.Address,
  2155. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS) +
  2156. (ULONG)Irp->IoStatus.Information,
  2157. SingleSR,
  2158. SingleSRLength,
  2159. &HeaderLength);
  2160. //
  2161. // Build the DLC UI frame header.
  2162. //
  2163. NbfBuildUIFrameHeader(&(Address->UIFrame->Header[HeaderLength]));
  2164. HeaderLength += sizeof(DLC_FRAME);
  2165. //
  2166. // Build the correct Netbios header.
  2167. //
  2168. if (Address->NetworkName != NULL) {
  2169. LocalName = Address->NetworkName->NetbiosName;
  2170. } else {
  2171. LocalName = DeviceContext->ReservedNetBIOSAddress;
  2172. }
  2173. if (remoteAddress == (PVOID)-1) {
  2174. ConstructDatagramBroadcast (
  2175. (PNBF_HDR_CONNECTIONLESS)&(Address->UIFrame->Header[HeaderLength]),
  2176. LocalName);
  2177. } else {
  2178. ConstructDatagram (
  2179. (PNBF_HDR_CONNECTIONLESS)&(Address->UIFrame->Header[HeaderLength]),
  2180. (PNAME)remoteAddress->NetbiosName,
  2181. LocalName);
  2182. }
  2183. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  2184. //
  2185. // Update our statistics for this datagram.
  2186. //
  2187. ++DeviceContext->Statistics.DatagramsSent;
  2188. ADD_TO_LARGE_INTEGER(
  2189. &DeviceContext->Statistics.DatagramBytesSent,
  2190. Irp->IoStatus.Information);
  2191. //
  2192. // Munge the packet length, append the data, and send it.
  2193. //
  2194. NbfSetNdisPacketLength(Address->UIFrame->NdisPacket, HeaderLength);
  2195. if (Irp->MdlAddress) {
  2196. NdisChainBufferAtBack (Address->UIFrame->NdisPacket, (PNDIS_BUFFER)Irp->MdlAddress);
  2197. }
  2198. NbfSendUIMdlFrame (
  2199. Address);
  2200. //
  2201. // The hold will be released in the I/O completion handler in
  2202. // UFRAMES.C. At that time, if there is another outstanding datagram
  2203. // to send, it will reset the hold and call this routine again.
  2204. //
  2205. } else {
  2206. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  2207. }
  2208. return STATUS_SUCCESS;
  2209. } /* NbfSendDatagramsOnAddress */