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.

3085 lines
96 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. Ntutil.c
  5. Abstract:
  6. This file contains a number of utility and support routines that are
  7. NT specific.
  8. Author:
  9. Jim Stewart (Jimst) 10-2-92
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "ntprocs.h"
  14. #include "stdio.h"
  15. #include <ntddtcp.h>
  16. #undef uint // undef to avoid a warning where tdiinfo.h redefines it
  17. #include <tcpinfo.h>
  18. #include <ipinfo.h>
  19. #include <tdiinfo.h>
  20. #include "ntddip.h" // Needed for PNETBT_PNP_RECONFIG_REQUEST
  21. #include <align.h>
  22. #include "ntutil.tmh"
  23. NTSTATUS
  24. CreateControlObject(
  25. tNBTCONFIG *pConfig
  26. );
  27. NTSTATUS
  28. NbtProcessDhcpRequest(
  29. tDEVICECONTEXT *pDeviceContext);
  30. VOID
  31. GetExtendedAttributes(
  32. tDEVICECONTEXT *pDeviceContext
  33. );
  34. PSTRM_PROCESSOR_LOG LogAlloc ;
  35. PSTRM_PROCESSOR_LOG LogFree ;
  36. extern tTIMERQ TimerQ;
  37. //******************* Pageable Routine Declarations ****************
  38. #ifdef ALLOC_PRAGMA
  39. #pragma CTEMakePageable(PAGE, NbtAllocAndInitDevice)
  40. #pragma CTEMakePageable(PAGE, CreateControlObject)
  41. #pragma CTEMakePageable(PAGE, NbtProcessDhcpRequest)
  42. #pragma CTEMakePageable(PAGE, NbtCreateAddressObjects)
  43. #pragma CTEMakePageable(PAGE, GetExtendedAttributes)
  44. #pragma CTEMakePageable(PAGE, ConvertToUlong)
  45. #pragma CTEMakePageable(PAGE, NbtInitMdlQ)
  46. #pragma CTEMakePageable(PAGE, NTZwCloseFile)
  47. #pragma CTEMakePageable(PAGE, NTReReadRegistry)
  48. #pragma CTEMakePageable(PAGE, DelayedNbtLogDuplicateNameEvent)
  49. #pragma CTEMakePageable(PAGE, DelayedNbtCloseFileHandles)
  50. #pragma CTEMakePageable(PAGE, SaveClientSecurity)
  51. #endif
  52. //******************* Pageable Routine Declarations ****************
  53. ulong
  54. GetUnique32BitValue(
  55. void
  56. )
  57. /*++
  58. Routine Description:
  59. Returns a reasonably unique 32-bit number based on the system clock.
  60. In NT, we take the current system time, convert it to milliseconds,
  61. and return the low 32 bits.
  62. Arguments:
  63. None.
  64. Return Value:
  65. A reasonably unique 32-bit value.
  66. --*/
  67. {
  68. LARGE_INTEGER ntTime, tmpTime;
  69. KeQuerySystemTime(&ntTime);
  70. tmpTime = CTEConvert100nsToMilliseconds(ntTime);
  71. return(tmpTime.LowPart);
  72. }
  73. //----------------------------------------------------------------------------
  74. NTSTATUS
  75. NbtAllocAndInitDevice(
  76. PUNICODE_STRING pucBindName,
  77. PUNICODE_STRING pucExportName,
  78. tDEVICECONTEXT **ppDeviceContext,
  79. enum eNbtDevice DeviceType
  80. )
  81. /*++
  82. Routine Description:
  83. This routine mainly allocates the device object and initializes some
  84. of its fields.
  85. Arguments:
  86. Return Value:
  87. status
  88. --*/
  89. {
  90. NTSTATUS Status;
  91. PUCHAR Buffer;
  92. ULONG LinkOffset;
  93. tDEVICECONTEXT *pDeviceContext;
  94. PDEVICE_OBJECT DeviceObject = NULL;
  95. CTEPagedCode();
  96. *ppDeviceContext = NULL;
  97. Buffer = NbtAllocMem(pucExportName->MaximumLength+pucBindName->MaximumLength,NBT_TAG('w'));
  98. if (Buffer == NULL)
  99. {
  100. return STATUS_INSUFFICIENT_RESOURCES;
  101. }
  102. Status = IoCreateDevice (NbtConfig.DriverObject, // Driver Object
  103. sizeof(tDEVICECONTEXT)-sizeof(DEVICE_OBJECT), // Device Extension
  104. pucExportName, // Device Name
  105. FILE_DEVICE_NETWORK, // Device type 0x12
  106. FILE_DEVICE_SECURE_OPEN, // Device Characteristics
  107. FALSE, // Exclusive
  108. &DeviceObject);
  109. if (!NT_SUCCESS( Status ))
  110. {
  111. KdPrint(("Nbt.NbtAllocAndInitDevice: FAILed <%x> ExportDevice=%wZ\n",Status,pucExportName));
  112. CTEMemFree (Buffer);
  113. return Status;
  114. }
  115. *ppDeviceContext = pDeviceContext = (tDEVICECONTEXT *)DeviceObject;
  116. //
  117. // zero out the data structure, beyond the OS specific part
  118. //
  119. LinkOffset = FIELD_OFFSET(tDEVICECONTEXT, Linkage);
  120. CTEZeroMemory (&pDeviceContext->Linkage, sizeof(tDEVICECONTEXT)-LinkOffset);
  121. // initialize the pDeviceContext data structure. There is one of
  122. // these data structured tied to each "device" that NBT exports
  123. // to higher layers (i.e. one for each network adapter that it
  124. // binds to.
  125. InitializeListHead (&pDeviceContext->Linkage); // Sets the forward link = back link = list head
  126. InitializeListHead (&pDeviceContext->UpConnectionInUse);
  127. InitializeListHead (&pDeviceContext->LowerConnection);
  128. InitializeListHead (&pDeviceContext->LowerConnFreeHead);
  129. InitializeListHead (&pDeviceContext->WaitingForInbound);
  130. #ifndef REMOVE_IF_TCPIP_FIX___GATEWAY_AFTER_NOTIFY_BUG
  131. pDeviceContext->DelayedNotification = NBT_TDI_NOACTION;
  132. KeInitializeEvent(&pDeviceContext->DelayedNotificationCompleteEvent, NotificationEvent, FALSE);
  133. #endif
  134. // put a verifier value into the structure so that we can check that
  135. // we are operating on the right data when the OS passes a device context
  136. // to NBT
  137. pDeviceContext->Verify = NBT_VERIFY_DEVCONTEXT;
  138. pDeviceContext->DeviceType = DeviceType; // Default
  139. CTEInitLock(&pDeviceContext->LockInfo.SpinLock); // setup the spin lock
  140. #if DBG
  141. pDeviceContext->LockInfo.LockNumber = DEVICE_LOCK;
  142. #endif
  143. pDeviceContext->RefCount = 1; // Dereferenced when the Device is destroyed
  144. // #if DBG
  145. pDeviceContext->ReferenceContexts[REF_DEV_CREATE]++;
  146. // #endif // DBG
  147. pDeviceContext->IPInterfaceContext = (ULONG)-1; // by default
  148. pDeviceContext->ExportName.MaximumLength = pucExportName->MaximumLength;
  149. pDeviceContext->ExportName.Buffer = (PWSTR)Buffer;
  150. RtlCopyUnicodeString(&pDeviceContext->ExportName,pucExportName);
  151. pDeviceContext->BindName.MaximumLength = pucBindName->MaximumLength;
  152. pDeviceContext->BindName.Buffer = (PWSTR)(Buffer+pucExportName->MaximumLength);
  153. RtlCopyUnicodeString(&pDeviceContext->BindName,pucBindName);
  154. KeInitializeEvent (&pDeviceContext->DeviceCleanedupEvent, NotificationEvent, FALSE);
  155. pDeviceContext->EnableNagling = FALSE;
  156. // IpAddress, AssignedIpAddress, and NumAdditionalIpAddresses fields should be = 0
  157. // DeviceRegistrationHandle and NetAddressRegistrationHandle should be NULL
  158. // DeviceRefreshState and WakeupPatternRefCount should also be = 0
  159. return (Status);
  160. }
  161. NTSTATUS
  162. NTQueryIPForInterfaceInfo(
  163. tDEVICECONTEXT *pDeviceContext
  164. )
  165. {
  166. PVOID *pIPInfo;
  167. PIP_INTERFACE_INFO pIPIfInfo;
  168. ULONG BufferLen;
  169. NTSTATUS status;
  170. ULONG NextAdapterNumber;
  171. UNICODE_STRING ucDeviceName;
  172. ULONG Input, Metric, IfContext;
  173. if (NT_SUCCESS (status = NbtQueryIpHandler (pDeviceContext->pControlFileObject,
  174. IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER,
  175. (PVOID *) &pDeviceContext->pFastSend)))
  176. {
  177. BufferLen = sizeof(PVOID *);
  178. if (NT_SUCCESS (status = NbtProcessIPRequest (IOCTL_IP_GET_BESTINTFC_FUNC_ADDR,
  179. NULL, // No Input buffer
  180. 0,
  181. (PVOID *) &pIPInfo,
  182. &BufferLen)))
  183. {
  184. pDeviceContext->pFastQuery = *pIPInfo;
  185. CTEMemFree (pIPInfo);
  186. pIPInfo = NULL;
  187. if (pDeviceContext->pFastQuery) {
  188. /*
  189. * Get the context for loopback IP address.
  190. */
  191. IfContext = 0xffff;
  192. pDeviceContext->pFastQuery (ntohl(INADDR_LOOPBACK), &IfContext, &Metric);
  193. if (IfContext != 0xffff) {
  194. NbtConfig.LoopbackIfContext = IfContext;
  195. }
  196. }
  197. }
  198. else
  199. {
  200. KdPrint (("Nbt.NTQueryIPForInterfaceInfo: ERROR: <%x> pFastQuery on Device:\n\t<%wZ>!\n",
  201. status, &pDeviceContext->BindName));
  202. pDeviceContext->pFastQuery = NULL;
  203. }
  204. }
  205. else
  206. {
  207. KdPrint (("Nbt.NTQueryIPForInterfaceInfo: ERROR:<%x>, Irql=<%d>,pFastSend on Device:\n\t<%wZ>!\n",
  208. status, KeGetCurrentIrql(), &pDeviceContext->BindName));
  209. pDeviceContext->pFastSend = NULL;
  210. }
  211. if ((pDeviceContext->DeviceType == NBT_DEVICE_NETBIOSLESS) ||
  212. (pDeviceContext->DeviceType == NBT_DEVICE_CLUSTER))
  213. {
  214. //
  215. // Cluster devices do not have any real InterfaceContext -- initialized to -1 by default
  216. //
  217. // Determine the InterfaceContext for the Loopback address
  218. //
  219. if ((NT_SUCCESS (status)) &&
  220. (pDeviceContext->DeviceType == NBT_DEVICE_NETBIOSLESS))
  221. {
  222. ASSERT (pDeviceContext->pFastQuery);
  223. pDeviceContext->pFastQuery (ntohl(INADDR_LOOPBACK), &pDeviceContext->IPInterfaceContext, &Metric);
  224. }
  225. }
  226. else if (NT_SUCCESS (status))
  227. {
  228. //
  229. // Get the InterfaceContext for this adapter
  230. //
  231. BufferLen = sizeof(IP_ADAPTER_INDEX_MAP) * (NbtConfig.AdapterCount+2);
  232. status = NbtProcessIPRequest (IOCTL_IP_INTERFACE_INFO,
  233. NULL, // No Input buffer
  234. 0,
  235. &pIPIfInfo,
  236. &BufferLen);
  237. if (NT_SUCCESS(status))
  238. {
  239. status = STATUS_UNSUCCESSFUL;
  240. for(NextAdapterNumber=0; NextAdapterNumber<(ULONG)pIPIfInfo->NumAdapters; NextAdapterNumber++)
  241. {
  242. ucDeviceName.Buffer = pIPIfInfo->Adapter[NextAdapterNumber].Name;
  243. ucDeviceName.Length = ucDeviceName.MaximumLength =
  244. (sizeof (WCHAR)) * wcslen(pIPIfInfo->Adapter[NextAdapterNumber].Name);
  245. IF_DBG(NBT_DEBUG_PNP_POWER)
  246. KdPrint (("[%d/%d]\t<%wZ>\n",
  247. NextAdapterNumber+1, pIPIfInfo->NumAdapters, &ucDeviceName));
  248. if (RtlCompareUnicodeString (&ucDeviceName, &pDeviceContext->BindName, TRUE) == 0)
  249. {
  250. pDeviceContext->IPInterfaceContext = pIPIfInfo->Adapter[NextAdapterNumber].Index;
  251. status = STATUS_SUCCESS;
  252. break;
  253. }
  254. }
  255. if (NT_SUCCESS(status))
  256. {
  257. BufferLen = sizeof (ULONG);
  258. Input = pDeviceContext->IPInterfaceContext;
  259. //
  260. // Query the latest WOL capabilities on this adapter!
  261. //
  262. if (NT_SUCCESS (status = NbtProcessIPRequest (IOCTL_IP_GET_WOL_CAPABILITY,
  263. &Input, // Input buffer
  264. BufferLen,
  265. (PVOID) &pIPInfo,
  266. &BufferLen)))
  267. {
  268. ASSERT (pIPInfo);
  269. pDeviceContext->WOLProperties = * ((PULONG) pIPInfo);
  270. CTEMemFree (pIPInfo);
  271. pIPInfo = NULL;
  272. }
  273. IF_DBG(NBT_DEBUG_PNP_POWER)
  274. KdPrint (("Nbt.NTQueryIPForInterfaceInfo[GET_WOL_CAPABILITY]: <%x>, pDeviceContext=<%p>, Input=<%x>, Result=<%x>\n",status, pDeviceContext, Input, pDeviceContext->WOLProperties));
  275. }
  276. else
  277. {
  278. KdPrint (("Nbt.NTQueryIPForInterfaceInfo: Could not find IpInterface from [%d]:\n<%wZ>\n",
  279. (ULONG)pIPIfInfo->NumAdapters, &pDeviceContext->BindName));
  280. }
  281. CTEMemFree (pIPIfInfo);
  282. }
  283. else
  284. {
  285. KdPrint (("Nbt.NTQueryIPForInterfaceInfo: ERROR<%x>, No InterfaceContext for Device:<%wZ>!\n",
  286. &pDeviceContext->BindName));
  287. }
  288. }
  289. return (status);
  290. }
  291. //----------------------------------------------------------------------------
  292. NTSTATUS
  293. NbtCreateDeviceObject(
  294. PUNICODE_STRING pucBindName,
  295. PUNICODE_STRING pucExportName,
  296. tADDRARRAY *pAddrs,
  297. tDEVICECONTEXT **ppDeviceContext,
  298. enum eNbtDevice DeviceType
  299. )
  300. /*++
  301. Routine Description:
  302. This routine initializes a Driver Object from the device object passed
  303. in and the name of the driver object passed in. After the Driver Object
  304. has been created, clients can "Open" the driver by that name.
  305. For the Netbiosless device, do not insert on device list.
  306. Arguments:
  307. Return Value:
  308. status - the outcome
  309. --*/
  310. {
  311. NTSTATUS status;
  312. PDEVICE_OBJECT DeviceObject = NULL;
  313. tDEVICECONTEXT *pDeviceContext;
  314. tDEVICECONTEXT *pDeviceContextOther;
  315. ULONG ulIpAddress;
  316. CTELockHandle OldIrq1;
  317. CTEULONGLONG NextAdapterMask;
  318. ULONG NextAdapterNumber;
  319. BOOLEAN fAttached = FALSE;
  320. BOOLEAN fInserted;
  321. #ifdef _NETBIOSLESS
  322. BOOLEAN fStopInitTimers = FALSE;
  323. if (DeviceType != NBT_DEVICE_NETBIOSLESS)
  324. #endif
  325. {
  326. //
  327. // We need to acquire this lock since we can have multiple devices
  328. // being added simultaneously and hence we will need to have a unique
  329. // Adapter Number for each device
  330. //
  331. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  332. //
  333. // Check to make sure we have not yet crossed the limit!
  334. //
  335. if (NbtConfig.AdapterCount >= NBT_MAXIMUM_BINDINGS)
  336. {
  337. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  338. KdPrint(("Nbt.NbtCreateDeviceObject: ERROR -- Cannot add new device=<%ws>, Max=<%d> reached\n",
  339. pucBindName->Buffer, NBT_MAXIMUM_BINDINGS));
  340. return (STATUS_INSUFFICIENT_RESOURCES);
  341. }
  342. NbtConfig.AdapterCount++;
  343. //
  344. // If this is the first Device, we need to start the Timers
  345. //
  346. if (NbtConfig.AdapterCount == 1)
  347. {
  348. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  349. status = InitTimersNotOs();
  350. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  351. //
  352. // If we failed and no one else also started the timers, then fail
  353. //
  354. if ((status != STATUS_SUCCESS) && (!(--NbtConfig.AdapterCount)))
  355. {
  356. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  357. KdPrint(("Nbt.NbtCreateDeviceObject: InitTimersNotOs FAILed, failing to add device %ws\n",
  358. pucBindName->Buffer));
  359. NbtLogEvent (EVENT_NBT_TIMERS, status, 0x112);
  360. StopInitTimers();
  361. return status;
  362. }
  363. }
  364. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  365. }
  366. status = NbtAllocAndInitDevice (pucBindName, pucExportName, ppDeviceContext, DeviceType);
  367. if (!NT_SUCCESS(status))
  368. {
  369. KdPrint(("Nbt.NbtCreateDeviceObject: NbtAllocAndInitDevice returned status=%X\n",status));
  370. //
  371. // If we failed to add the first device stop the timers
  372. //
  373. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  374. #ifdef _NETBIOSLESS
  375. // SmbDevice does not affect adapter count
  376. if ((DeviceType != NBT_DEVICE_NETBIOSLESS) &&
  377. (!(--NbtConfig.AdapterCount)))
  378. #else
  379. if (!(--NbtConfig.AdapterCount))
  380. #endif
  381. {
  382. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  383. StopInitTimers();
  384. }
  385. else
  386. {
  387. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  388. }
  389. return(status);
  390. }
  391. DeviceObject = (PDEVICE_OBJECT) (pDeviceContext = *ppDeviceContext);
  392. //
  393. // for a Bnode pAddrs is NULL
  394. //
  395. if (pAddrs)
  396. {
  397. #ifdef MULTIPLE_WINS
  398. int i;
  399. #endif
  400. pDeviceContext->lNameServerAddress = pAddrs->NameServerAddress;
  401. pDeviceContext->lBackupServer = pAddrs->BackupServer;
  402. pDeviceContext->RefreshToBackup = 0;
  403. pDeviceContext->SwitchedToBackup = 0;
  404. #ifdef MULTIPLE_WINS
  405. pDeviceContext->lNumOtherServers = pAddrs->NumOtherServers;
  406. pDeviceContext->lLastResponsive = 0;
  407. for (i = 0; i < pAddrs->NumOtherServers; i++)
  408. {
  409. pDeviceContext->lOtherServers[i] = pAddrs->Others[i];
  410. }
  411. #endif
  412. #ifdef _NETBIOSLESS
  413. pDeviceContext->NetbiosEnabled = pAddrs->NetbiosEnabled;
  414. IF_DBG(NBT_DEBUG_PNP_POWER)
  415. KdPrint(("Nbt.NbtCreateDeviceObject: %wZ NetbiosEnabled = %d\n",
  416. &pDeviceContext->ExportName, pDeviceContext->NetbiosEnabled));
  417. #endif
  418. pDeviceContext->RasProxyFlags = pAddrs->RasProxyFlags;
  419. pDeviceContext->EnableNagling = pAddrs->EnableNagling;
  420. //
  421. // if the node type is set to Bnode by default then switch to Hnode if
  422. // there are any WINS servers configured.
  423. //
  424. if ((NodeType & DEFAULT_NODE_TYPE) &&
  425. (pAddrs->NameServerAddress || pAddrs->BackupServer))
  426. {
  427. NodeType = MSNODE | (NodeType & PROXY);
  428. }
  429. }
  430. #ifdef _NETBIOSLESS
  431. else
  432. {
  433. pDeviceContext->NetbiosEnabled = TRUE;
  434. pDeviceContext->RasProxyFlags = 0;
  435. pDeviceContext->EnableNagling = FALSE;
  436. }
  437. #endif
  438. CTEAttachFsp(&fAttached, REF_FSP_CREATE_DEVICE);
  439. status = NbtTdiOpenControl(pDeviceContext);
  440. if (NT_SUCCESS (status))
  441. {
  442. status = NTQueryIPForInterfaceInfo (pDeviceContext);
  443. }
  444. else
  445. {
  446. KdPrint(("Nbt.NbtCreateDeviceObject: NbtTdiOpenControl returned status=%X\n",status));
  447. }
  448. CTEDetachFsp(fAttached, REF_FSP_CREATE_DEVICE);
  449. if (NT_SUCCESS(status))
  450. {
  451. // increase the stack size of our device object, over that of the transport
  452. // so that clients create Irps large enough
  453. // to pass on to the transport below.
  454. // In theory, we should just add 1 here, to account for our presence in the
  455. // driver chain.
  456. //
  457. DeviceObject->StackSize = pDeviceContext->pControlDeviceObject->StackSize + 1;
  458. if (NbtConfig.MaxIrpStackSize < DeviceObject->StackSize) {
  459. NbtConfig.MaxIrpStackSize = DeviceObject->StackSize;
  460. }
  461. //
  462. // Get an Irp for the out of resource queue (used to disconnect sessions
  463. // when really low on memory)
  464. //
  465. if (!NbtConfig.OutOfRsrc.pIrp)
  466. {
  467. NbtConfig.OutOfRsrc.pIrp = IoAllocateIrp(pDeviceContext->DeviceObject.StackSize, FALSE);
  468. if (NbtConfig.OutOfRsrc.pIrp)
  469. {
  470. //
  471. // allocate a dpc structure and keep it: we might need if we hit an
  472. // out-of-resource condition
  473. //
  474. NbtConfig.OutOfRsrc.pDpc = NbtAllocMem(sizeof(KDPC),NBT_TAG('a'));
  475. if (!NbtConfig.OutOfRsrc.pDpc)
  476. {
  477. IoFreeIrp(NbtConfig.OutOfRsrc.pIrp);
  478. NbtConfig.OutOfRsrc.pIrp = NULL;
  479. }
  480. }
  481. if ((!NbtConfig.OutOfRsrc.pIrp) || (!NbtConfig.OutOfRsrc.pDpc))
  482. {
  483. KdPrint(("Nbt.NbtCreateDeviceObject: Could not create OutOfRsrc Irps!\n"));
  484. status = STATUS_INSUFFICIENT_RESOURCES;
  485. }
  486. }
  487. }
  488. if (!NT_SUCCESS (status))
  489. {
  490. //
  491. // We failed somewhere, so clean up!
  492. //
  493. if (pDeviceContext->hControl)
  494. {
  495. CTEAttachFsp(&fAttached, REF_FSP_CREATE_DEVICE);
  496. ObDereferenceObject(pDeviceContext->pControlFileObject);
  497. NTZwCloseFile(pDeviceContext->hControl);
  498. pDeviceContext->pControlFileObject = NULL;
  499. pDeviceContext->hControl = NULL;
  500. CTEDetachFsp(fAttached, REF_FSP_CREATE_DEVICE);
  501. }
  502. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  503. //
  504. // If this was the last Device to go away, stop the timers
  505. // (SmbDevice does not affect adapter count)
  506. //
  507. if (DeviceType == NBT_DEVICE_NETBIOSLESS)
  508. {
  509. if (!(NbtConfig.AdapterCount))
  510. {
  511. fStopInitTimers = TRUE;
  512. }
  513. }
  514. else if (!(--NbtConfig.AdapterCount))
  515. {
  516. fStopInitTimers = TRUE;
  517. }
  518. else if (NbtConfig.AdapterCount == 1)
  519. {
  520. NbtConfig.MultiHomed = FALSE;
  521. }
  522. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  523. if (fStopInitTimers)
  524. {
  525. StopInitTimers();
  526. }
  527. *ppDeviceContext = NULL;
  528. CTEMemFree (pDeviceContext->ExportName.Buffer);
  529. IoDeleteDevice((PDEVICE_OBJECT)pDeviceContext);
  530. NbtLogEvent (EVENT_NBT_CREATE_DEVICE, status, 0x113);
  531. return (status);
  532. }
  533. pDeviceContext->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
  534. #ifdef _NETBIOSLESS
  535. pDeviceContext->SessionPort = NBT_SESSION_TCP_PORT;
  536. pDeviceContext->NameServerPort = NBT_NAMESERVICE_UDP_PORT;
  537. pDeviceContext->DatagramPort = NBT_DATAGRAM_UDP_PORT;
  538. RtlZeroMemory (pDeviceContext->MessageEndpoint, NETBIOS_NAME_SIZE);
  539. #endif
  540. //
  541. // An instance number is assigned to each device so that the service which
  542. // creates logical devices in Nbt can re-use these devices in case it fails
  543. // to destroy them in a prev. instance.
  544. //
  545. pDeviceContext->InstanceNumber = GetUnique32BitValue();
  546. //
  547. // Now set the Adapter number for this device
  548. //
  549. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  550. //
  551. // See if we have a gap in the AdapterMask of the current set of Devices
  552. // which we can utilize
  553. //
  554. #ifdef _NETBIOSLESS
  555. // SmbDevice does not affect adapter count
  556. if (IsDeviceNetbiosless(pDeviceContext))
  557. {
  558. NextAdapterNumber = 0;
  559. NextAdapterMask = 0xffffffffffffffff;
  560. }
  561. else
  562. #endif
  563. {
  564. NextAdapterNumber = 1; // 0 is for the SmbDevice!
  565. NextAdapterMask = 1;
  566. fInserted = FALSE;
  567. if (!IsListEmpty(&NbtConfig.DeviceContexts))
  568. {
  569. PLIST_ENTRY pHead, pEntry;
  570. tDEVICECONTEXT *pTmpDevContext;
  571. pHead = &NbtConfig.DeviceContexts;
  572. pEntry = pHead;
  573. while ((pEntry = pEntry->Flink) != pHead)
  574. {
  575. pTmpDevContext = CONTAINING_RECORD(pEntry,tDEVICECONTEXT,Linkage);
  576. if (pTmpDevContext->AdapterMask > NextAdapterMask)
  577. {
  578. pDeviceContext->Linkage.Flink = pEntry;
  579. pDeviceContext->Linkage.Blink = pEntry->Blink;
  580. pEntry->Blink->Flink = &pDeviceContext->Linkage;
  581. pEntry->Blink = &pDeviceContext->Linkage;
  582. fInserted = TRUE;
  583. break;
  584. }
  585. NextAdapterNumber++;
  586. NextAdapterMask = (pTmpDevContext->AdapterMask) << 1;
  587. }
  588. }
  589. if (!fInserted)
  590. {
  591. // add this new device context on to end of the List in the
  592. // configuration data structure
  593. InsertTailList(&NbtConfig.DeviceContexts, &pDeviceContext->Linkage);
  594. }
  595. NbtConfig.CurrentAdaptersMask |= NextAdapterMask;
  596. }
  597. if ((1+NbtConfig.AdapterCount) > NbtConfig.RemoteCacheLen) // Add 1 for the SmbDevice
  598. {
  599. NbtConfig.RemoteCacheLen += REMOTE_CACHE_INCREMENT;
  600. }
  601. // We keep a bit mask around to keep track of this adapter number so we can
  602. // quickly find if a given name is registered on a particular adapter,
  603. // by a corresponding bit set in the tNAMEADDR - local hash table entry
  604. //
  605. pDeviceContext->AdapterMask = NextAdapterMask;
  606. pDeviceContext->AdapterNumber = NextAdapterNumber;
  607. IF_DBG(NBT_DEBUG_NTUTIL)
  608. KdPrint (("Nbt.NbtCreateDeviceObject: Device=<%x>, New AdapterCount=<%d>, AdapterMask=<%lx:%lx>\n",
  609. pDeviceContext, NbtConfig.AdapterCount, NextAdapterMask));
  610. if (NbtConfig.AdapterCount > 1)
  611. {
  612. NbtConfig.MultiHomed = TRUE;
  613. }
  614. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  615. return(STATUS_SUCCESS);
  616. }
  617. //----------------------------------------------------------------------------
  618. tDEVICECONTEXT *
  619. GetDeviceWithIPAddress(
  620. tIPADDRESS IpAddress
  621. )
  622. /*++
  623. Routine Description:
  624. This Routine references the device with preferably the requested
  625. IP address, otherwise, it will pick the first device with
  626. a valid IP address
  627. This routine must be called with the JointLock held!
  628. Arguments:
  629. Return Value:
  630. pDeviceContext
  631. --*/
  632. {
  633. LIST_ENTRY *pEntry;
  634. LIST_ENTRY *pHead;
  635. tDEVICECONTEXT *pDeviceContext;
  636. tDEVICECONTEXT *pDeviceContextWithIp = NULL;
  637. if (!IpAddress)
  638. {
  639. return NULL;
  640. }
  641. //
  642. // Find the device with this Ip address
  643. //
  644. pHead = pEntry = &NbtConfig.DeviceContexts;
  645. while ((pEntry = pEntry->Flink) != pHead)
  646. {
  647. pDeviceContext = CONTAINING_RECORD (pEntry,tDEVICECONTEXT,Linkage);
  648. if (pDeviceContext->IpAddress)
  649. {
  650. if (IpAddress == pDeviceContext->IpAddress)
  651. {
  652. return pDeviceContext;
  653. }
  654. else if (!pDeviceContextWithIp)
  655. {
  656. pDeviceContextWithIp = pDeviceContext;
  657. }
  658. }
  659. }
  660. //
  661. // Couldn't find a Device with the requested IP address!
  662. // So, in the meantime return the first valid Device with an IP address (if any)
  663. //
  664. return pDeviceContextWithIp;
  665. }
  666. //----------------------------------------------------------------------------
  667. #define MAX_REFERENCES 5000
  668. BOOLEAN
  669. NBT_REFERENCE_DEVICE(
  670. IN tDEVICECONTEXT *pDeviceContext,
  671. IN ULONG ReferenceContext,
  672. IN BOOLEAN fLocked
  673. )
  674. {
  675. BOOLEAN fStatus;
  676. CTELockHandle OldIrq;
  677. if (!fLocked)
  678. {
  679. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  680. }
  681. if (NBT_VERIFY_HANDLE (pDeviceContext, NBT_VERIFY_DEVCONTEXT))
  682. {
  683. InterlockedIncrement(&pDeviceContext->RefCount);
  684. // #if DBG
  685. pDeviceContext->ReferenceContexts[ReferenceContext]++;
  686. ASSERT (pDeviceContext->ReferenceContexts[ReferenceContext] <= MAX_REFERENCES);
  687. // #endif // DBG
  688. fStatus = TRUE;
  689. }
  690. else
  691. {
  692. fStatus = FALSE;
  693. }
  694. if (!fLocked)
  695. {
  696. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  697. }
  698. return (fStatus);
  699. }
  700. VOID
  701. NBT_DEREFERENCE_DEVICE(
  702. IN tDEVICECONTEXT *pDeviceContext,
  703. IN ULONG ReferenceContext,
  704. IN BOOLEAN fLocked
  705. )
  706. /*++
  707. Routine Description:
  708. This Routine Dereferences the DeviceContext and queues it on
  709. to the worker thread if the the Device needs to be deleted
  710. This routine may be called with the JointLock held!
  711. Arguments:
  712. pContext
  713. Return Value:
  714. NONE
  715. --*/
  716. {
  717. CTELockHandle OldIrq;
  718. if (!fLocked)
  719. {
  720. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  721. }
  722. ASSERT (NBT_VERIFY_HANDLE2(pDeviceContext, NBT_VERIFY_DEVCONTEXT, NBT_VERIFY_DEVCONTEXT_DOWN));
  723. ASSERT (pDeviceContext->ReferenceContexts[ReferenceContext]);
  724. // #if DBG
  725. pDeviceContext->ReferenceContexts[ReferenceContext]--;
  726. // #endif // DBG
  727. if (!(--pDeviceContext->RefCount))
  728. {
  729. #if DBG
  730. {
  731. ULONG i;
  732. for (i=0; i<REF_DEV_MAX; i++)
  733. {
  734. ASSERT(0 == pDeviceContext->ReferenceContexts[i]);
  735. }
  736. }
  737. #endif // DBG
  738. //
  739. // We cannot delete the device directly here since we are at raised Irql
  740. //
  741. NTQueueToWorkerThread(
  742. &pDeviceContext->WorkItemDeleteDevice,
  743. DelayedNbtDeleteDevice,
  744. NULL,
  745. pDeviceContext,
  746. NULL,
  747. NULL,
  748. TRUE);
  749. }
  750. if (!fLocked)
  751. {
  752. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  753. }
  754. }
  755. NTSTATUS
  756. NbtDestroyDevice(
  757. IN tDEVICECONTEXT *pDeviceContext,
  758. IN BOOLEAN fWait
  759. )
  760. {
  761. LIST_ENTRY *pEntry;
  762. LIST_ENTRY *pHead;
  763. tTIMERQENTRY *pTimer;
  764. COMPLETIONCLIENT pClientCompletion;
  765. PVOID Context;
  766. CTELockHandle OldIrq;
  767. BOOLEAN fRemoveFromSmbList = FALSE;
  768. tDEVICECONTEXT *pSavedSmbDevice = NULL;
  769. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  770. if (!NBT_VERIFY_HANDLE(pDeviceContext, NBT_VERIFY_DEVCONTEXT))
  771. {
  772. ASSERT (NBT_VERIFY_HANDLE(pDeviceContext, NBT_VERIFY_DEVCONTEXT_DOWN));
  773. return (STATUS_INVALID_DEVICE_REQUEST);
  774. }
  775. //
  776. // First remove the Device from the NbtConfig list
  777. // (no-op for Wins and SmbDevice)
  778. //
  779. RemoveEntryList (&pDeviceContext->Linkage);
  780. if ((pDeviceContext->DeviceType != NBT_DEVICE_NETBIOSLESS) &&
  781. (pDeviceContext->IPInterfaceContext != (ULONG)-1))
  782. {
  783. if (pDeviceContext->AdapterMask & NbtConfig.ServerMask) {
  784. fRemoveFromSmbList = TRUE;
  785. NbtConfig.ServerMask &= (~pDeviceContext->AdapterMask);
  786. }
  787. NbtConfig.ClientMask &= (~pDeviceContext->AdapterMask);
  788. }
  789. pDeviceContext->Verify = NBT_VERIFY_DEVCONTEXT_DOWN;
  790. //
  791. // Clear out the DeviceContext entry from the IPContext-to-Device Map
  792. //
  793. if (!IsDeviceNetbiosless(pDeviceContext)) {
  794. NbtConfig.CurrentAdaptersMask &= ~pDeviceContext->AdapterMask;
  795. }
  796. //
  797. // Remove any pending requests in the LmHosts or Dns or CheckAddrs Q's
  798. // This has to be done immediately after we change the device
  799. // state before releasing the lock.
  800. //
  801. TimeoutLmHRequests (NULL, pDeviceContext, TRUE, &OldIrq);
  802. if ((fRemoveFromSmbList) &&
  803. (pNbtSmbDevice) && !gbDestroyingSmbDevice &&
  804. (NBT_REFERENCE_DEVICE (pNbtSmbDevice, REF_DEV_SMB_BIND, TRUE)))
  805. {
  806. pSavedSmbDevice = pNbtSmbDevice;
  807. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  808. //
  809. // Set the Session port info
  810. //
  811. if (pSavedSmbDevice->hSession)
  812. {
  813. NbtSetTcpInfo (pSavedSmbDevice->hSession,
  814. AO_OPTION_DEL_IFLIST,
  815. INFO_TYPE_ADDRESS_OBJECT,
  816. pDeviceContext->IPInterfaceContext);
  817. }
  818. //
  819. // Now, set the same for the Datagram port
  820. //
  821. if ((pSavedSmbDevice->pFileObjects) &&
  822. (pSavedSmbDevice->pFileObjects->hDgram))
  823. {
  824. NbtSetTcpInfo (pSavedSmbDevice->pFileObjects->hDgram,
  825. AO_OPTION_DEL_IFLIST,
  826. INFO_TYPE_ADDRESS_OBJECT,
  827. pDeviceContext->IPInterfaceContext);
  828. }
  829. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  830. NBT_DEREFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, TRUE);
  831. }
  832. //
  833. // If we still have any timers running on this Device, stop them!
  834. //
  835. pHead = &TimerQ.ActiveHead;
  836. pEntry = pHead->Flink;
  837. while (pEntry != pHead)
  838. {
  839. pTimer = CONTAINING_RECORD(pEntry,tTIMERQENTRY,Linkage);
  840. if (pTimer->pDeviceContext == (PVOID) pDeviceContext)
  841. {
  842. StopTimer(pTimer,&pClientCompletion,&Context);
  843. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  844. if (pClientCompletion)
  845. {
  846. (*pClientCompletion)(Context, STATUS_TIMEOUT);
  847. }
  848. IF_DBG(NBT_DEBUG_NTUTIL)
  849. KdPrint(("NbtDestroyDevice: stopped timer on this Device")) ;
  850. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  851. pEntry = pHead->Flink; // Restart from the beginning since we released the lock
  852. }
  853. else
  854. {
  855. pEntry = pEntry->Flink;
  856. }
  857. }
  858. // Now do the Dereference which will cause this Device to be destroyed!
  859. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_CREATE, TRUE);
  860. if (fWait)
  861. {
  862. NTSTATUS status;
  863. InitializeListHead (&pDeviceContext->Linkage);
  864. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  865. IF_DBG(NBT_DEBUG_PNP_POWER)
  866. KdPrint(("Nbt.NbtDestroyDevice: Waiting on Device=<%p>:\n\t%wZ\n",
  867. pDeviceContext, &pDeviceContext->ExportName));
  868. //
  869. // Wait for all pending Timer and worker requests which have referenced this
  870. // Device to complete!
  871. //
  872. status = KeWaitForSingleObject (&pDeviceContext->DeviceCleanedupEvent, // Object to wait on.
  873. Executive, // Reason for waiting
  874. KernelMode, // Processor mode
  875. FALSE, // Alertable
  876. NULL); // Timeout
  877. ASSERT(status == STATUS_SUCCESS);
  878. KdPrint(("Nbt.NbtDestroyDevice: *** Destroying Device *** \n\t%wZ\n", &pDeviceContext->ExportName));
  879. RemoveEntryList(&pDeviceContext->Linkage);
  880. CTEMemFree (pDeviceContext->ExportName.Buffer);
  881. IoDeleteDevice((PDEVICE_OBJECT)pDeviceContext);
  882. }
  883. else
  884. {
  885. //
  886. // Put it here so that the Cleanup routine can find this Device
  887. //
  888. InsertTailList(&NbtConfig.DevicesAwaitingDeletion,&pDeviceContext->Linkage);
  889. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  890. }
  891. return (STATUS_SUCCESS);
  892. }
  893. /*******************************************************************
  894. NAME: DelayedNbtDeleteDevice
  895. SYNOPSIS: This Routine is the worker thread for Deleting the
  896. DeviceObject at PASSIVE level Irql
  897. ENTRY: pDeviceContext - name of the device/ device ptr
  898. Return Value: NONE
  899. ********************************************************************/
  900. VOID
  901. DelayedNbtDeleteDevice(
  902. IN tDGRAM_SEND_TRACKING *pUnused1,
  903. IN PVOID pContext,
  904. IN PVOID pUnused2,
  905. IN tDEVICECONTEXT *pUnused3
  906. )
  907. {
  908. LIST_ENTRY * pEntry;
  909. LIST_ENTRY * pHead;
  910. LIST_ENTRY * pClientEntry;
  911. LIST_ENTRY TempList;
  912. tDEVICECONTEXT * pTmpDeviceContext;
  913. tDEVICECONTEXT * pNextDeviceContext;
  914. tCLIENTELE * pClientEle;
  915. tCLIENTELE * pLastClient;
  916. tADDRESSELE * pAddress;
  917. tADDRESSELE * pLastAddress;
  918. tNAMEADDR * pNameAddr;
  919. tCONNECTELE * pConnEle;
  920. tLOWERCONNECTION * pLowerConn;
  921. tTIMERQENTRY * pTimer;
  922. COMPLETIONCLIENT pClientCompletion;
  923. PVOID Context;
  924. tDGRAM_SEND_TRACKING * pTracker;
  925. CTELockHandle OldIrq;
  926. CTELockHandle OldIrq1;
  927. CTELockHandle OldIrq2;
  928. int i;
  929. WCHAR Buffer[MAX_PATH];
  930. UNICODE_STRING ucExportName;
  931. PUNICODE_STRING pucExportName;
  932. BOOLEAN Attached;
  933. #ifdef _PNP_POWER_
  934. NTSTATUS Status;
  935. #endif // _PNP_POWER_
  936. BOOLEAN fDelSmbDevice = FALSE;
  937. BOOLEAN fStopInitTimers = FALSE;
  938. BOOLEAN fNameReferenced = FALSE;
  939. tDEVICECONTEXT * pDeviceContext = (tDEVICECONTEXT *) pContext;
  940. ASSERT (NBT_VERIFY_HANDLE(pDeviceContext, NBT_VERIFY_DEVCONTEXT_DOWN));
  941. //
  942. // Mark in the device extension that this is not a valid device anymore
  943. //
  944. pDeviceContext->Verify += 10;
  945. //
  946. // DeRegister this Device for our clients
  947. //
  948. if (pDeviceContext->NetAddressRegistrationHandle)
  949. {
  950. Status = TdiDeregisterNetAddress (pDeviceContext->NetAddressRegistrationHandle);
  951. pDeviceContext->NetAddressRegistrationHandle = NULL;
  952. NbtTrace(NBT_TRACE_PNP, ("DeregisterNetAddress: ExportName=%Z BindName=%Z status=%!status!",
  953. &pDeviceContext->ExportName, &pDeviceContext->BindName, Status));
  954. }
  955. if (pDeviceContext->DeviceRegistrationHandle)
  956. {
  957. Status = TdiDeregisterDeviceObject (pDeviceContext->DeviceRegistrationHandle);
  958. pDeviceContext->DeviceRegistrationHandle = NULL;
  959. NbtTrace(NBT_TRACE_PNP, ("DeregisterDevice: ExportName=%Z BindName=%Z status=%!status!",
  960. &pDeviceContext->ExportName, &pDeviceContext->BindName, Status));
  961. }
  962. if (!IsDeviceNetbiosless(pDeviceContext)) {
  963. NbtRemovePermanentName(pDeviceContext);
  964. }
  965. if (pDeviceContext->IpAddress)
  966. {
  967. if (IsDeviceNetbiosless(pDeviceContext))
  968. {
  969. IF_DBG(NBT_DEBUG_PNP_POWER)
  970. KdPrint (("Nbt.DelayedNbtDeleteDevice: device %wZ deregistered\n",
  971. &(pDeviceContext->ExportName) ));
  972. }
  973. CloseAddressesWithTransport(pDeviceContext);
  974. //
  975. // Dhcp is has passed down a null IP address meaning that it has
  976. // lost the lease on the previous address, so close all connections
  977. // to the transport - pLowerConn.
  978. //
  979. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  980. DisableInboundConnections (pDeviceContext);
  981. CTEExReleaseResource(&NbtConfig.Resource);
  982. }
  983. if (pDeviceContext->pControlFileObject)
  984. {
  985. BOOLEAN Attached;
  986. CTEAttachFsp(&Attached, REF_FSP_DELETE_DEVICE);
  987. ObDereferenceObject(pDeviceContext->pControlFileObject);
  988. IF_DBG(NBT_DEBUG_HANDLES)
  989. KdPrint (("\t --< ><====<%x>\tDelayedNbtDeleteDevice->ObDereferenceObject\n", pDeviceContext->pControlFileObject));
  990. Status = ZwClose(pDeviceContext->hControl);
  991. IF_DBG(NBT_DEBUG_HANDLES)
  992. KdPrint (("\t<===<%x>\tDelayedNbtDeleteDevice->ZwClose, status = <%x>\n", pDeviceContext->hControl, Status));
  993. pDeviceContext->pControlFileObject = NULL;
  994. pDeviceContext->hControl = NULL;
  995. CTEDetachFsp(Attached, REF_FSP_DELETE_DEVICE);
  996. }
  997. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  998. CTESpinLock(pDeviceContext,OldIrq1);
  999. ASSERT(IsListEmpty(&pDeviceContext->LowerConnFreeHead));
  1000. //
  1001. // walk through all names and see if any is being registered on this
  1002. // device context: if so, stop and complete it!
  1003. //
  1004. for (i=0;i < NbtConfig.pLocalHashTbl->lNumBuckets ;i++ )
  1005. {
  1006. pHead = &NbtConfig.pLocalHashTbl->Bucket[i];
  1007. pEntry = pHead->Flink;
  1008. while (pEntry != pHead)
  1009. {
  1010. pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
  1011. //
  1012. // if a name registration or refresh or release was started for this name
  1013. // on this device context, stop the timer. (Completion routine will take care of
  1014. // doing registration on other device contexts if applicable)
  1015. //
  1016. if ((pTimer = pNameAddr->pTimer) &&
  1017. (pTracker = pTimer->Context) &&
  1018. (pTracker->pDeviceContext == pDeviceContext))
  1019. {
  1020. ASSERT(pTracker->pNameAddr == pNameAddr);
  1021. pNameAddr->pTimer = NULL;
  1022. StopTimer(pTimer,&pClientCompletion,&Context);
  1023. NBT_REFERENCE_NAMEADDR (pNameAddr, REF_NAME_DELETE_DEVICE);
  1024. fNameReferenced = TRUE;
  1025. CTESpinFree(pDeviceContext,OldIrq1);
  1026. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1027. if (pClientCompletion)
  1028. {
  1029. (*pClientCompletion)(Context,STATUS_TIMEOUT);
  1030. }
  1031. IF_DBG(NBT_DEBUG_NTUTIL)
  1032. KdPrint(("DelayedNbtDeleteDevice: stopped name reg timer")) ;
  1033. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1034. CTESpinLock(pDeviceContext,OldIrq1);
  1035. }
  1036. pEntry = pEntry->Flink;
  1037. if (fNameReferenced)
  1038. {
  1039. fNameReferenced = FALSE;
  1040. NBT_REFERENCE_NAMEADDR (pNameAddr, REF_NAME_DELETE_DEVICE);
  1041. }
  1042. }
  1043. }
  1044. CTESpinFree(pDeviceContext,OldIrq1);
  1045. //
  1046. // Walk through the AddressHead list. If any addresses exist and they
  1047. // point to this device context, put the next device context. Also, update
  1048. // adapter mask to reflect that this device context is now gone.
  1049. //
  1050. pLastAddress = NULL;
  1051. pLastClient = NULL;
  1052. pHead = pEntry = &NbtConfig.AddressHead;
  1053. while ((pEntry = pEntry->Flink) != pHead)
  1054. {
  1055. pAddress = CONTAINING_RECORD(pEntry,tADDRESSELE,Linkage);
  1056. ASSERT (pAddress->Verify == NBT_VERIFY_ADDRESS);
  1057. //
  1058. // Keep this Address around until we are done
  1059. //
  1060. NBT_REFERENCE_ADDRESS (pAddress, REF_ADDR_DEL_DEVICE);
  1061. //
  1062. // If we had referenced a previous address, Deref it now!
  1063. //
  1064. if (pLastAddress)
  1065. {
  1066. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1067. //
  1068. // The last Client may need to have the address present
  1069. // while dereferencing, so deref it if we need to!
  1070. //
  1071. if (pLastClient)
  1072. {
  1073. NBT_DEREFERENCE_CLIENT(pLastClient);
  1074. pLastClient = NULL;
  1075. }
  1076. NBT_DEREFERENCE_ADDRESS (pLastAddress, REF_ADDR_DEL_DEVICE);
  1077. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1078. }
  1079. pLastAddress = pAddress; // => Save this so that we can Deref it later
  1080. //
  1081. // Need AddressLock to traverse ClientHead
  1082. //
  1083. CTESpinLock (pAddress, OldIrq2);
  1084. pClientEntry = &pAddress->ClientHead;
  1085. while ((pClientEntry = pClientEntry->Flink) != &pAddress->ClientHead)
  1086. {
  1087. pClientEle = CONTAINING_RECORD (pClientEntry,tCLIENTELE,Linkage);
  1088. if (pClientEle->pDeviceContext == pDeviceContext)
  1089. {
  1090. CTESpinFree(pAddress, OldIrq2);
  1091. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1092. KdPrint(("Nbt.DelayedNbtDeleteDevice: Client:Context <%-16.16s:%x>:<%x>, EVReceive:EVContext=<%x:%x>\n\tFAILed to Cleanup on Device<%x>\n",
  1093. pAddress->pNameAddr->Name, pAddress->pNameAddr->Name[15],
  1094. pClientEle, pClientEle->evReceive, pClientEle->RcvEvContext, pDeviceContext));
  1095. if (pLastClient)
  1096. {
  1097. NBT_DEREFERENCE_CLIENT(pLastClient);
  1098. }
  1099. pClientEle->pIrp = NULL;
  1100. NbtCleanUpAddress(pClientEle,pDeviceContext);
  1101. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1102. CTESpinLock (pAddress, OldIrq2);
  1103. pLastClient = pClientEle; // pClientEle still needs one more Deref
  1104. }
  1105. }
  1106. if (!IsDeviceNetbiosless(pDeviceContext)) {
  1107. pAddress->pNameAddr->AdapterMask &= (~pDeviceContext->AdapterMask); // Clear Adapter Mask
  1108. pAddress->pNameAddr->ConflictMask &= (~pDeviceContext->AdapterMask);
  1109. }
  1110. if ((!(pAddress->pNameAddr->AdapterMask)) &&
  1111. (pAddress->pNameAddr->NameTypeState & STATE_CONFLICT))
  1112. {
  1113. pAddress->pNameAddr->NameTypeState &= (~NAME_STATE_MASK);
  1114. pAddress->pNameAddr->NameTypeState |= STATE_RESOLVED;
  1115. }
  1116. CTESpinFree(pAddress, OldIrq2);
  1117. }
  1118. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1119. //
  1120. // If we had referenced a previous Client or Address, Deref it now!
  1121. //
  1122. if (pLastClient)
  1123. {
  1124. NBT_DEREFERENCE_CLIENT(pLastClient);
  1125. }
  1126. if (pLastAddress)
  1127. {
  1128. NBT_DEREFERENCE_ADDRESS (pLastAddress, REF_ADDR_DEL_DEVICE);
  1129. }
  1130. //
  1131. // if a call was started, but aborted then we could have some memory here!
  1132. //
  1133. while (!IsListEmpty(&pDeviceContext->UpConnectionInUse))
  1134. {
  1135. pEntry = RemoveHeadList(&pDeviceContext->UpConnectionInUse);
  1136. pConnEle = CONTAINING_RECORD(pEntry,tCONNECTELE,Linkage);
  1137. NBT_DEREFERENCE_CONNECTION (pConnEle, REF_CONN_CREATE);
  1138. }
  1139. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1140. CTESpinLock(pDeviceContext,OldIrq1);
  1141. //
  1142. // We have finished our regular cleanup, so now close all the remaining TDI handles
  1143. //
  1144. while (!IsListEmpty(&pDeviceContext->LowerConnection))
  1145. {
  1146. pEntry = RemoveHeadList(&pDeviceContext->LowerConnection);
  1147. InitializeListHead (pEntry);
  1148. pLowerConn = CONTAINING_RECORD(pEntry,tLOWERCONNECTION,Linkage);
  1149. IF_DBG(NBT_DEBUG_NTUTIL)
  1150. KdPrint (("Nbt.DelayedNbtDeleteDevice: Dereferencing pLowerConn <%x>\n", pLowerConn));
  1151. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_CREATE, TRUE);
  1152. }
  1153. CTESpinFree(pDeviceContext,OldIrq1);
  1154. //
  1155. // If this was the last Device to go away, stop the timers
  1156. // (SmbDevice does not affect adapter count)
  1157. //
  1158. if (IsDeviceNetbiosless(pDeviceContext))
  1159. {
  1160. if (!(NbtConfig.AdapterCount))
  1161. {
  1162. //
  1163. // No more devices funtioning, so stop the timers now!
  1164. //
  1165. fStopInitTimers = TRUE;
  1166. }
  1167. }
  1168. else if (!(--NbtConfig.AdapterCount))
  1169. {
  1170. fStopInitTimers = TRUE;
  1171. }
  1172. else if (NbtConfig.AdapterCount == 1)
  1173. {
  1174. NbtConfig.MultiHomed = FALSE;
  1175. }
  1176. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1177. if (fStopInitTimers)
  1178. {
  1179. StopInitTimers();
  1180. }
  1181. //
  1182. // Now set the event for the waiting thread to complete!
  1183. //
  1184. KeSetEvent(&pDeviceContext->DeviceCleanedupEvent, 0, FALSE);
  1185. }
  1186. tDEVICECONTEXT *
  1187. GetDeviceFromInterface(
  1188. IN tIPADDRESS IpAddress,
  1189. IN BOOLEAN fReferenceDevice
  1190. )
  1191. {
  1192. LIST_ENTRY *pEntry;
  1193. LIST_ENTRY *pHead;
  1194. CTELockHandle OldIrq;
  1195. ULONG IPInterfaceContext, Metric;
  1196. tDEVICECONTEXT *pDeviceContext;
  1197. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1198. if (IsListEmpty(&NbtConfig.DeviceContexts))
  1199. {
  1200. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1201. return (NULL);
  1202. }
  1203. pDeviceContext = CONTAINING_RECORD(NbtConfig.DeviceContexts.Flink, tDEVICECONTEXT, Linkage);
  1204. NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  1205. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1206. pDeviceContext->pFastQuery(IpAddress, &IPInterfaceContext, &Metric);
  1207. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1208. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  1209. pHead = pEntry = &NbtConfig.DeviceContexts;
  1210. while ((pEntry = pEntry->Flink) != pHead)
  1211. {
  1212. pDeviceContext = CONTAINING_RECORD (pEntry,tDEVICECONTEXT,Linkage);
  1213. if (pDeviceContext->IPInterfaceContext == IPInterfaceContext)
  1214. {
  1215. if (fReferenceDevice)
  1216. {
  1217. NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_OUT_FROM_IP, TRUE);
  1218. }
  1219. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1220. return pDeviceContext;
  1221. }
  1222. }
  1223. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1224. return (NULL);
  1225. }
  1226. //----------------------------------------------------------------------------
  1227. tDEVICECONTEXT *
  1228. GetAndRefNextDeviceFromNameAddr(
  1229. IN tNAMEADDR *pNameAddr
  1230. )
  1231. /*++
  1232. Routine Description:
  1233. This routine finds the first adapter as specified in the name's adapter
  1234. mask and set the DeviceContext associated with it. It then clears the
  1235. bit in the adapter mask of pNameAddr.
  1236. Arguments:
  1237. Return Value:
  1238. pDeviceContext if found a successful device!
  1239. --*/
  1240. {
  1241. CTEULONGLONG AdapterMask = 1;
  1242. tDEVICECONTEXT *pDeviceContext = NULL;
  1243. PLIST_ENTRY pHead;
  1244. PLIST_ENTRY pEntry;
  1245. //
  1246. // We may encounter an adapter for which the device is no
  1247. // longer there, so we loop until we find the first valid
  1248. // adapter or the mask is clear
  1249. //
  1250. while (pNameAddr->ReleaseMask)
  1251. {
  1252. //
  1253. // Get the lowest AdapterMask bit and clear it in pNameAddr since
  1254. // we are releasing the Name on that Adapter now
  1255. //
  1256. AdapterMask = ~(pNameAddr->ReleaseMask - 1) & pNameAddr->ReleaseMask;
  1257. pNameAddr->ReleaseMask &= ~AdapterMask;
  1258. //
  1259. // Get the DeviceContext for this adapter mask
  1260. //
  1261. pHead = &NbtConfig.DeviceContexts;
  1262. pEntry = pHead->Flink;
  1263. while (pEntry != pHead)
  1264. {
  1265. pDeviceContext = CONTAINING_RECORD(pEntry,tDEVICECONTEXT,Linkage);
  1266. if (pDeviceContext->AdapterMask == AdapterMask)
  1267. {
  1268. //
  1269. // Found a valid device on which this name is registered
  1270. //
  1271. #ifndef VXD
  1272. NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_GET_REF, TRUE);
  1273. #endif
  1274. return pDeviceContext;
  1275. }
  1276. //
  1277. // Go to next device
  1278. //
  1279. pEntry = pEntry->Flink;
  1280. }
  1281. }
  1282. return NULL;
  1283. }
  1284. //----------------------------------------------------------------------------
  1285. NTSTATUS
  1286. CreateControlObject(
  1287. tNBTCONFIG *pConfig)
  1288. /*++
  1289. Routine Description:
  1290. This routine allocates memory for the provider info block, tacks it
  1291. onto the global configuration and sets default values for each item.
  1292. Arguments:
  1293. Return Value:
  1294. NTSTATUS
  1295. --*/
  1296. {
  1297. tCONTROLOBJECT *pControl;
  1298. CTEPagedCode();
  1299. pControl = (tCONTROLOBJECT *) NbtAllocMem (sizeof(tCONTROLOBJECT), NBT_TAG2('21'));
  1300. if (!pControl)
  1301. {
  1302. return(STATUS_INSUFFICIENT_RESOURCES);
  1303. }
  1304. pControl->Verify = NBT_VERIFY_CONTROL;
  1305. pControl->ProviderInfo.Version = 1;
  1306. pControl->ProviderInfo.MaxSendSize = 0;
  1307. pControl->ProviderInfo.MaxConnectionUserData = 0;
  1308. // we need to get these values from the transport underneath...*TODO*
  1309. // since the RDR uses this value
  1310. pControl->ProviderInfo.MaxDatagramSize = 0;
  1311. pControl->ProviderInfo.ServiceFlags = 0;
  1312. /* pControl->ProviderInfo.TransmittedTsdus = 0;
  1313. pControl->ProviderInfo.ReceivedTsdus = 0;
  1314. pControl->ProviderInfo.TransmissionErrors = 0;
  1315. pControl->ProviderInfo.ReceiveErrors = 0;
  1316. */
  1317. pControl->ProviderInfo.MinimumLookaheadData = 0;
  1318. pControl->ProviderInfo.MaximumLookaheadData = 0;
  1319. /* pControl->ProviderInfo.DiscardedFrames = 0;
  1320. pControl->ProviderInfo.OversizeTsdusReceived = 0;
  1321. pControl->ProviderInfo.UndersizeTsdusReceived = 0;
  1322. pControl->ProviderInfo.MulticastTsdusReceived = 0;
  1323. pControl->ProviderInfo.BroadcastTsdusReceived = 0;
  1324. pControl->ProviderInfo.MulticastTsdusTransmitted = 0;
  1325. pControl->ProviderInfo.BroadcastTsdusTransmitted = 0;
  1326. pControl->ProviderInfo.SendTimeouts = 0;
  1327. pControl->ProviderInfo.ReceiveTimeouts = 0;
  1328. pControl->ProviderInfo.ConnectionIndicationsReceived = 0;
  1329. pControl->ProviderInfo.ConnectionIndicationsAccepted = 0;
  1330. pControl->ProviderInfo.ConnectionsInitiated = 0;
  1331. pControl->ProviderInfo.ConnectionsAccepted = 0;
  1332. */
  1333. // put a ptr to this info into the pConfig so we can locate it
  1334. // when we want to cleanup
  1335. pConfig->pControlObj = pControl;
  1336. /* KEEP THIS STUFF HERE SINCE WE MAY NEED TO ALSO CREATE PROVIDER STATS!!
  1337. *TODO*
  1338. DeviceList[i].ProviderStats.Version = 2;
  1339. DeviceList[i].ProviderStats.OpenConnections = 0;
  1340. DeviceList[i].ProviderStats.ConnectionsAfterNoRetry = 0;
  1341. DeviceList[i].ProviderStats.ConnectionsAfterRetry = 0;
  1342. DeviceList[i].ProviderStats.LocalDisconnects = 0;
  1343. DeviceList[i].ProviderStats.RemoteDisconnects = 0;
  1344. DeviceList[i].ProviderStats.LinkFailures = 0;
  1345. DeviceList[i].ProviderStats.AdapterFailures = 0;
  1346. DeviceList[i].ProviderStats.SessionTimeouts = 0;
  1347. DeviceList[i].ProviderStats.CancelledConnections = 0;
  1348. DeviceList[i].ProviderStats.RemoteResourceFailures = 0;
  1349. DeviceList[i].ProviderStats.LocalResourceFailures = 0;
  1350. DeviceList[i].ProviderStats.NotFoundFailures = 0;
  1351. DeviceList[i].ProviderStats.NoListenFailures = 0;
  1352. DeviceList[i].ProviderStats.DatagramsSent = 0;
  1353. DeviceList[i].ProviderStats.DatagramBytesSent.HighPart = 0;
  1354. DeviceList[i].ProviderStats.DatagramBytesSent.LowPart = 0;
  1355. DeviceList[i].ProviderStats.DatagramsReceived = 0;
  1356. DeviceList[i].ProviderStats.DatagramBytesReceived.HighPart = 0;
  1357. DeviceList[i].ProviderStats.DatagramBytesReceived.LowPart = 0;
  1358. DeviceList[i].ProviderStats.PacketsSent = 0;
  1359. DeviceList[i].ProviderStats.PacketsReceived = 0;
  1360. DeviceList[i].ProviderStats.DataFramesSent = 0;
  1361. DeviceList[i].ProviderStats.DataFrameBytesSent.HighPart = 0;
  1362. DeviceList[i].ProviderStats.DataFrameBytesSent.LowPart = 0;
  1363. DeviceList[i].ProviderStats.DataFramesReceived = 0;
  1364. DeviceList[i].ProviderStats.DataFrameBytesReceived.HighPart = 0;
  1365. DeviceList[i].ProviderStats.DataFrameBytesReceived.LowPart = 0;
  1366. DeviceList[i].ProviderStats.DataFramesResent = 0;
  1367. DeviceList[i].ProviderStats.DataFrameBytesResent.HighPart = 0;
  1368. DeviceList[i].ProviderStats.DataFrameBytesResent.LowPart = 0;
  1369. DeviceList[i].ProviderStats.DataFramesRejected = 0;
  1370. DeviceList[i].ProviderStats.DataFrameBytesRejected.HighPart = 0;
  1371. DeviceList[i].ProviderStats.DataFrameBytesRejected.LowPart = 0;
  1372. DeviceList[i].ProviderStats.ResponseTimerExpirations = 0;
  1373. DeviceList[i].ProviderStats.AckTimerExpirations = 0;
  1374. DeviceList[i].ProviderStats.MaximumSendWindow = 0;
  1375. DeviceList[i].ProviderStats.AverageSendWindow = 0;
  1376. DeviceList[i].ProviderStats.PiggybackAckQueued = 0;
  1377. DeviceList[i].ProviderStats.PiggybackAckTimeouts = 0;
  1378. DeviceList[i].ProviderStats.WastedPacketSpace.HighPart = 0;
  1379. DeviceList[i].ProviderStats.WastedPacketSpace.LowPart = 0;
  1380. DeviceList[i].ProviderStats.WastedSpacePackets = 0;
  1381. DeviceList[i].ProviderStats.NumberOfResources = 0;
  1382. */
  1383. return(STATUS_SUCCESS);
  1384. }
  1385. VOID
  1386. DelayedNbtCloseFileHandles(
  1387. IN tDGRAM_SEND_TRACKING *pUnused1,
  1388. IN PVOID pContext,
  1389. IN PVOID pUnused2,
  1390. IN tDEVICECONTEXT *pUnused3
  1391. )
  1392. {
  1393. BOOLEAN Attached = FALSE;
  1394. NTSTATUS Status;
  1395. tFILE_OBJECTS *pFileObjects = (tFILE_OBJECTS *) pContext;
  1396. CTEPagedCode();
  1397. CTEAttachFsp(&Attached, REF_FSP_CLOSE_FILE_HANDLES);
  1398. if (pFileObjects->pNameServerFileObject)
  1399. {
  1400. ObDereferenceObject((PVOID *)pFileObjects->pNameServerFileObject);
  1401. IF_DBG(NBT_DEBUG_HANDLES)
  1402. KdPrint (("\t --< ><====<%x>\tDelayedNbtCloseFileHandles->ObDereferenceObject\n",
  1403. pFileObjects->pNameServerFileObject));
  1404. Status = ZwClose(pFileObjects->hNameServer);
  1405. IF_DBG(NBT_DEBUG_HANDLES)
  1406. KdPrint (("\t<===<%x>\tDelayedNbtCloseFileHandles->ZwClose, status = <%x>\n",
  1407. pFileObjects->hNameServer, Status));
  1408. NbtTrace(NBT_TRACE_PNP, ("close NameServer UDP handle pFileObjects %p", pFileObjects));
  1409. }
  1410. if (pFileObjects->pDgramFileObject)
  1411. {
  1412. ObDereferenceObject((PVOID *) pFileObjects->pDgramFileObject);
  1413. IF_DBG(NBT_DEBUG_HANDLES)
  1414. KdPrint (("\t --< ><====<%x>\tDelayedNbtCloseFileHandles->ObDereferenceObject\n",
  1415. pFileObjects->pDgramFileObject));
  1416. Status = ZwClose(pFileObjects->hDgram);
  1417. IF_DBG(NBT_DEBUG_HANDLES)
  1418. KdPrint (("\t<===<%x>\tDelayedNbtCloseFileHandles->ZwClose, status = <%x>\n",
  1419. pFileObjects->hDgram, Status));
  1420. NbtTrace(NBT_TRACE_PNP, ("close Datagram UDP handle on pFileObjects %p", pFileObjects));
  1421. }
  1422. CTEDetachFsp(Attached, REF_FSP_CLOSE_FILE_HANDLES);
  1423. CTEMemFree (pFileObjects);
  1424. }
  1425. //----------------------------------------------------------------------------
  1426. NTSTATUS
  1427. CloseAddressesWithTransport(
  1428. IN tDEVICECONTEXT *pDeviceContext
  1429. )
  1430. /*++
  1431. Routine Description:
  1432. This routine checks each device context to see if there are any open
  1433. connections, and returns SUCCESS if there are.
  1434. Arguments:
  1435. Return Value:
  1436. none
  1437. --*/
  1438. {
  1439. BOOLEAN Attached;
  1440. CTELockHandle OldIrq;
  1441. PFILE_OBJECT pNSFileObject, pSFileObject, pDGFileObject;
  1442. #ifdef _PNP_POWER_
  1443. PFILE_OBJECT pCFileObject;
  1444. NTSTATUS Status;
  1445. #endif // _PNP_POWER_
  1446. tFILE_OBJECTS *pFileObjects = NULL;
  1447. HANDLE hSession = NULL;
  1448. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  1449. pDeviceContext->IpAddress = 0;
  1450. //
  1451. // Check for the existence of Objects under SpinLock and
  1452. // then Close them outside of the SpinLock
  1453. //
  1454. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1455. pSFileObject = pDeviceContext->pSessionFileObject;
  1456. pDeviceContext->pSessionFileObject = NULL;
  1457. hSession = pDeviceContext->hSession;
  1458. pDeviceContext->hSession = NULL;
  1459. pFileObjects = pDeviceContext->pFileObjects;
  1460. pDeviceContext->pFileObjects = NULL;
  1461. if ((pFileObjects) &&
  1462. (--pFileObjects->RefCount > 0))
  1463. {
  1464. NbtTrace(NBT_TRACE_PNP, ("closing UDP handle on deivce %p will be delayed. (pFileObjects %p)",
  1465. pDeviceContext, pFileObjects));
  1466. pFileObjects = NULL;
  1467. }
  1468. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1469. CTEExReleaseResource(&NbtConfig.Resource);
  1470. //
  1471. // Now close all the necessary objects as appropriate
  1472. //
  1473. CTEAttachFsp(&Attached, REF_FSP_CLOSE_ADDRESSES);
  1474. if (pSFileObject)
  1475. {
  1476. ObDereferenceObject((PVOID *)pSFileObject);
  1477. IF_DBG(NBT_DEBUG_HANDLES)
  1478. KdPrint (("\t --< ><====<%x>\tCloseAddressesWithTransport2->ObDereferenceObject\n", pSFileObject));
  1479. Status = ZwClose(hSession);
  1480. IF_DBG(NBT_DEBUG_HANDLES)
  1481. KdPrint (("\t<===<%x>\tCloseAddressesWithTransport2->ZwClose, status = <%x>\n", hSession, Status));
  1482. NbtTrace(NBT_TRACE_PNP, ("close TCP session handle on device %p", pDeviceContext));
  1483. }
  1484. if (pFileObjects)
  1485. {
  1486. DelayedNbtCloseFileHandles (NULL, pFileObjects, NULL, NULL);
  1487. }
  1488. CTEDetachFsp(Attached, REF_FSP_CLOSE_ADDRESSES);
  1489. return(STATUS_SUCCESS);
  1490. }
  1491. //----------------------------------------------------------------------------
  1492. NTSTATUS
  1493. NbtCreateAddressObjects(
  1494. IN ULONG IpAddress,
  1495. IN ULONG SubnetMask,
  1496. OUT tDEVICECONTEXT *pDeviceContext)
  1497. /*++
  1498. Routine Description:
  1499. This routine gets the ip address and subnet mask out of the registry
  1500. to calcuate the broadcast address. It then creates the address objects
  1501. with the transport.
  1502. Arguments:
  1503. pucRegistryPath - path to NBT config info in registry
  1504. pucBindName - name of the service to bind to.
  1505. pDeviceContext - ptr to the device context... place to store IP addr
  1506. and Broadcast address permanently
  1507. Return Value:
  1508. none
  1509. --*/
  1510. {
  1511. NTSTATUS status, locstatus;
  1512. ULONG ValueMask;
  1513. UCHAR IpAddrByte;
  1514. tFILE_OBJECTS *pFileObjects;
  1515. CTEPagedCode();
  1516. if (!(pFileObjects = (tFILE_OBJECTS *) NbtAllocMem (sizeof(tFILE_OBJECTS), NBT_TAG2('39'))))
  1517. {
  1518. KdPrint(("Nbt.NbtCreateAddressObjects: Failed to allocate memory for FileObject context!\n"));
  1519. return STATUS_INSUFFICIENT_RESOURCES;
  1520. }
  1521. CTEZeroMemory(pFileObjects, sizeof(tFILE_OBJECTS));
  1522. pFileObjects->RefCount = 1;
  1523. //
  1524. // to get the broadcast address combine the IP address with the subnet mask
  1525. // to yield a value with 1's in the "local" portion and the IP address
  1526. // in the network portion
  1527. //
  1528. ValueMask = (SubnetMask & IpAddress) | (~SubnetMask & -1);
  1529. IF_DBG(NBT_DEBUG_NTUTIL)
  1530. KdPrint(("Broadcastaddress = %X\n",ValueMask));
  1531. //
  1532. // the registry can be configured to set the subnet broadcast address to
  1533. // -1 rather than use the actual subnet broadcast address. This code
  1534. // checks for that and sets the broadcast address accordingly.
  1535. //
  1536. if (NbtConfig.UseRegistryBcastAddr)
  1537. {
  1538. pDeviceContext->BroadcastAddress = NbtConfig.RegistryBcastAddr;
  1539. }
  1540. else
  1541. {
  1542. pDeviceContext->BroadcastAddress = ValueMask;
  1543. }
  1544. pDeviceContext->IpAddress = IpAddress;
  1545. pDeviceContext->SubnetMask = SubnetMask;
  1546. //
  1547. // get the network number by checking the top bits in the ip address,
  1548. // looking for 0 or 10 or 110 or 1110
  1549. //
  1550. IpAddrByte = ((PUCHAR)&IpAddress)[3];
  1551. if ((IpAddrByte & 0x80) == 0)
  1552. {
  1553. // class A address - one byte netid
  1554. IpAddress &= 0xFF000000;
  1555. }
  1556. else if ((IpAddrByte & 0xC0) ==0x80)
  1557. {
  1558. // class B address - two byte netid
  1559. IpAddress &= 0xFFFF0000;
  1560. }
  1561. else if ((IpAddrByte & 0xE0) ==0xC0)
  1562. {
  1563. // class C address - three byte netid
  1564. IpAddress &= 0xFFFFFF00;
  1565. }
  1566. pDeviceContext->NetMask = IpAddress;
  1567. // now create the address objects.
  1568. // open the Ip Address for inbound Datagrams.
  1569. status = NbtTdiOpenAddress (&pFileObjects->hDgram,
  1570. &pFileObjects->pDgramDeviceObject,
  1571. &pFileObjects->pDgramFileObject,
  1572. pDeviceContext,
  1573. #ifdef _NETBIOSLESS
  1574. pDeviceContext->DatagramPort,
  1575. #else
  1576. (USHORT)NBT_DATAGRAM_UDP_PORT,
  1577. #endif
  1578. pDeviceContext->IpAddress,
  1579. 0); // not a TCP port
  1580. if (NT_SUCCESS(status))
  1581. {
  1582. #ifdef _NETBIOSLESS
  1583. if (pDeviceContext->NameServerPort == 0)
  1584. {
  1585. pFileObjects->hNameServer = NULL;
  1586. pFileObjects->pNameServerDeviceObject = NULL;
  1587. pFileObjects->pNameServerFileObject = NULL;
  1588. }
  1589. else
  1590. #endif
  1591. {
  1592. // open the Nameservice UDP port ..
  1593. status = NbtTdiOpenAddress (&pFileObjects->hNameServer,
  1594. &pFileObjects->pNameServerDeviceObject,
  1595. &pFileObjects->pNameServerFileObject,
  1596. pDeviceContext,
  1597. #ifdef _NETBIOSLESS
  1598. pDeviceContext->NameServerPort,
  1599. #else
  1600. (USHORT)NBT_NAMESERVICE_UDP_PORT,
  1601. #endif
  1602. pDeviceContext->IpAddress,
  1603. 0); // not a TCP port
  1604. }
  1605. if (NT_SUCCESS(status))
  1606. {
  1607. #ifdef _NETBIOSLESS
  1608. IF_DBG(NBT_DEBUG_NTUTIL)
  1609. KdPrint(("Nbt.NbtCreateAddressObjects: Open Session Port=<%d>, pDeviceContext=<%x>\n",
  1610. pDeviceContext->SessionPort, pDeviceContext));
  1611. #endif
  1612. // Open the TCP port for Session Services
  1613. status = NbtTdiOpenAddress (&pDeviceContext->hSession,
  1614. &pDeviceContext->pSessionDeviceObject,
  1615. &pDeviceContext->pSessionFileObject,
  1616. pDeviceContext,
  1617. #ifdef _NETBIOSLESS
  1618. pDeviceContext->SessionPort,
  1619. #else
  1620. (USHORT)NBT_SESSION_TCP_PORT,
  1621. #endif
  1622. pDeviceContext->IpAddress,
  1623. TCP_FLAG | SESSION_FLAG); // TCP port
  1624. if (NT_SUCCESS(status))
  1625. {
  1626. //
  1627. // This will get the MAC address for a RAS connection
  1628. // which is zero until there really is a connection to
  1629. // the RAS server
  1630. //
  1631. GetExtendedAttributes(pDeviceContext);
  1632. //
  1633. // If this is P-to-P, and the Subnet mask is all 1's, set broadcast
  1634. // address to all 1's and limit broadcast to this interface only
  1635. //
  1636. if ((pDeviceContext->IpInterfaceFlags & (IP_INTFC_FLAG_P2P | IP_INTFC_FLAG_P2MP)) &&
  1637. (SubnetMask == DEFAULT_BCAST_ADDR)) // If SubnetMask == -1 and connection is P-to-P
  1638. {
  1639. pDeviceContext->BroadcastAddress = DEFAULT_BCAST_ADDR;
  1640. if (pFileObjects->hNameServer)
  1641. {
  1642. NbtSetTcpInfo (pFileObjects->hNameServer,
  1643. AO_OPTION_LIMIT_BCASTS,
  1644. INFO_TYPE_ADDRESS_OBJECT,
  1645. (ULONG)TRUE);
  1646. }
  1647. if (pFileObjects->hDgram)
  1648. {
  1649. NbtSetTcpInfo (pFileObjects->hDgram,
  1650. AO_OPTION_LIMIT_BCASTS,
  1651. INFO_TYPE_ADDRESS_OBJECT,
  1652. (ULONG)TRUE);
  1653. }
  1654. }
  1655. ASSERT (!pDeviceContext->pFileObjects);
  1656. pDeviceContext->pFileObjects = pFileObjects;
  1657. return(status);
  1658. }
  1659. IF_DBG(NBT_DEBUG_NTUTIL)
  1660. KdPrint(("Nbt.NbtCreateAddressObjects: Error opening Session address with TDI, status=<%x>\n",status));
  1661. //
  1662. // Ensure that the Object pointers are NULLed out!
  1663. //
  1664. pDeviceContext->pSessionFileObject = NULL;
  1665. ObDereferenceObject(pFileObjects->pNameServerFileObject);
  1666. IF_DBG(NBT_DEBUG_HANDLES)
  1667. KdPrint (("\t --< ><====<%x>\tNbtCreateAddressObjects1->ObDereferenceObject\n", pFileObjects->pNameServerFileObject));
  1668. pFileObjects->pNameServerFileObject = NULL;
  1669. locstatus = NTZwCloseFile(pFileObjects->hNameServer);
  1670. IF_DBG(NBT_DEBUG_HANDLES)
  1671. KdPrint (("\t<===<%x>\tNbtCreateAddressObjects1->NTZwCloseFile (NameServer), status = <%x>\n", pFileObjects->hNameServer, locstatus));
  1672. }
  1673. ObDereferenceObject(pFileObjects->pDgramFileObject);
  1674. IF_DBG(NBT_DEBUG_HANDLES)
  1675. KdPrint (("\t --< ><====<%x>\tNbtCreateAddressObjects2->ObDereferenceObject\n", pFileObjects->pDgramFileObject));
  1676. pFileObjects->pDgramFileObject = NULL;
  1677. locstatus = NTZwCloseFile(pFileObjects->hDgram);
  1678. IF_DBG(NBT_DEBUG_HANDLES)
  1679. KdPrint (("\t<===<%x>\tNbtCreateAddressObjects2->NTZwCloseFile (Dgram), status = <%x>\n", pFileObjects->hDgram, locstatus));
  1680. IF_DBG(NBT_DEBUG_NTUTIL)
  1681. KdPrint(("Unable to Open NameServer port with TDI, status = %X\n",status));
  1682. }
  1683. CTEMemFree (pFileObjects);
  1684. return(status);
  1685. }
  1686. //----------------------------------------------------------------------------
  1687. VOID
  1688. GetExtendedAttributes(
  1689. tDEVICECONTEXT *pDeviceContext
  1690. )
  1691. /*++
  1692. Routine Description:
  1693. This routine converts a unicode dotted decimal to a ULONG
  1694. Arguments:
  1695. Return Value:
  1696. none
  1697. --*/
  1698. {
  1699. NTSTATUS status;
  1700. TCP_REQUEST_QUERY_INFORMATION_EX QueryReq;
  1701. IO_STATUS_BLOCK IoStatus;
  1702. HANDLE event;
  1703. IO_STATUS_BLOCK IoStatusBlock;
  1704. NTSTATUS Status;
  1705. OBJECT_ATTRIBUTES ObjectAttributes;
  1706. PFILE_FULL_EA_INFORMATION EaBuffer;
  1707. UNICODE_STRING DeviceName;
  1708. HANDLE hTcp;
  1709. ULONG Length;
  1710. UCHAR pBuffer[256];
  1711. ULONG BufferSize = 256;
  1712. BOOLEAN Attached = FALSE;
  1713. PWSTR pName = L"Tcp";
  1714. CTEPagedCode();
  1715. //
  1716. // Open a control channel to TCP for this IOCTL.
  1717. //
  1718. // NOTE: We cannot use the hControl in the DeviceContext since that was created in the context
  1719. // of the system process (address arrival from TCP/IP). Here, we are in the context of the service
  1720. // process (Ioctl down from DHCP) and so we need to open another control channel.
  1721. //
  1722. // NOTE: We still need to maintain the earlier call to create a control channel since that is
  1723. // used to submit TDI requests down to TCP/IP.
  1724. //
  1725. // copy device name into the unicode string
  1726. Status = CreateDeviceString(pName,&DeviceName);
  1727. if (!NT_SUCCESS(Status))
  1728. {
  1729. return;
  1730. }
  1731. #ifdef HDL_FIX
  1732. InitializeObjectAttributes (&ObjectAttributes, &DeviceName, OBJ_KERNEL_HANDLE, NULL, NULL);
  1733. #else
  1734. InitializeObjectAttributes (&ObjectAttributes, &DeviceName, 0, NULL, NULL);
  1735. #endif // HDL_FIX
  1736. IF_DBG(NBT_DEBUG_TDIADDR)
  1737. KdPrint(("Nbt.GetExtendedAttributes: Tcp device to open = %ws\n", DeviceName.Buffer));
  1738. EaBuffer = NULL;
  1739. Status = ZwCreateFile (&hTcp,
  1740. GENERIC_READ | GENERIC_WRITE,
  1741. &ObjectAttributes, // object attributes.
  1742. &IoStatusBlock, // returned status information.
  1743. NULL, // block size (unused).
  1744. FILE_ATTRIBUTE_NORMAL, // file attributes.
  1745. 0,
  1746. FILE_CREATE,
  1747. 0, // create options.
  1748. (PVOID)EaBuffer, // EA buffer.
  1749. 0); // Ea length
  1750. CTEMemFree(DeviceName.Buffer);
  1751. IF_DBG(NBT_DEBUG_TDIADDR)
  1752. KdPrint( ("OpenControl CreateFile Status:%X, IoStatus:%X\n", Status, IoStatusBlock.Status));
  1753. if ( NT_SUCCESS( Status ))
  1754. {
  1755. //
  1756. // Initialize the TDI information buffers.
  1757. //
  1758. //
  1759. // pass in the ipaddress as the first ULONG of the context array
  1760. //
  1761. *(ULONG *)QueryReq.Context = htonl(pDeviceContext->IpAddress);
  1762. QueryReq.ID.toi_entity.tei_entity = CL_NL_ENTITY;
  1763. QueryReq.ID.toi_entity.tei_instance = 0;
  1764. QueryReq.ID.toi_class = INFO_CLASS_PROTOCOL;
  1765. QueryReq.ID.toi_type = INFO_TYPE_PROVIDER;
  1766. QueryReq.ID.toi_id = IP_INTFC_INFO_ID;
  1767. status = ZwCreateEvent(&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
  1768. if (!NT_SUCCESS(status))
  1769. {
  1770. ZwClose( hTcp );
  1771. return;
  1772. }
  1773. //
  1774. // Make the actual TDI call
  1775. //
  1776. status = ZwDeviceIoControlFile (hTcp,
  1777. event,
  1778. NULL,
  1779. NULL,
  1780. &IoStatus,
  1781. IOCTL_TCP_QUERY_INFORMATION_EX,
  1782. &QueryReq,
  1783. sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
  1784. pBuffer,
  1785. BufferSize);
  1786. //
  1787. // If the call pended and we were supposed to wait for completion,
  1788. // then wait.
  1789. //
  1790. if ( status == STATUS_PENDING )
  1791. {
  1792. status = NtWaitForSingleObject (event, FALSE, NULL);
  1793. ASSERT(status == STATUS_SUCCESS);
  1794. }
  1795. if (NT_SUCCESS(status))
  1796. {
  1797. pDeviceContext->IpInterfaceFlags = ((IPInterfaceInfo *) pBuffer)->iii_flags;
  1798. //
  1799. // get the length of the mac address in case is is less than 6 bytes
  1800. //
  1801. Length = (((IPInterfaceInfo *)pBuffer)->iii_addrlength < sizeof(tMAC_ADDRESS))
  1802. ? ((IPInterfaceInfo *)pBuffer)->iii_addrlength : sizeof(tMAC_ADDRESS);
  1803. CTEZeroMemory(pDeviceContext->MacAddress.Address,sizeof(tMAC_ADDRESS));
  1804. CTEMemCopy(&pDeviceContext->MacAddress.Address[0], ((IPInterfaceInfo *)pBuffer)->iii_addr,Length);
  1805. }
  1806. status = ZwClose(event);
  1807. ASSERT (NT_SUCCESS(status));
  1808. //
  1809. // Close the handle to TCP since we dont need it anymore; all TDI requests go thru the
  1810. // Control handle in the DeviceContext.
  1811. //
  1812. status = ZwClose(hTcp);
  1813. ASSERT (NT_SUCCESS(status));
  1814. status = IoStatus.Status;
  1815. }
  1816. else
  1817. {
  1818. KdPrint(("Nbt:Failed to Open the control connection to the transport, status1 = %X\n", Status));
  1819. }
  1820. return;
  1821. }
  1822. //----------------------------------------------------------------------------
  1823. NTSTATUS
  1824. ConvertToUlong(
  1825. IN PUNICODE_STRING pucAddress,
  1826. OUT ULONG *pulValue)
  1827. /*++
  1828. Routine Description:
  1829. This routine converts a unicode dotted decimal to a ULONG
  1830. Arguments:
  1831. Return Value:
  1832. none
  1833. --*/
  1834. {
  1835. NTSTATUS status;
  1836. OEM_STRING OemAddress;
  1837. // create integer from unicode string
  1838. CTEPagedCode();
  1839. status = RtlUnicodeStringToAnsiString(&OemAddress, pucAddress, TRUE);
  1840. if (!NT_SUCCESS(status))
  1841. {
  1842. return(status);
  1843. }
  1844. status = ConvertDottedDecimalToUlong(OemAddress.Buffer,pulValue);
  1845. RtlFreeAnsiString(&OemAddress);
  1846. if (!NT_SUCCESS(status))
  1847. {
  1848. IF_DBG(NBT_DEBUG_NTUTIL)
  1849. KdPrint(("ERR: Bad Dotted Decimal Ip Address(must be <=255 with 4 dots) = %ws\n",
  1850. pucAddress->Buffer));
  1851. return(status);
  1852. }
  1853. return(STATUS_SUCCESS);
  1854. }
  1855. //----------------------------------------------------------------------------
  1856. VOID
  1857. NbtGetMdl(
  1858. PMDL *ppMdl,
  1859. enum eBUFFER_TYPES eBuffType)
  1860. /*++
  1861. Routine Description:
  1862. This routine allocates an Mdl.
  1863. Arguments:
  1864. ppListHead - a ptr to a ptr to the list head to add buffer to
  1865. iNumBuffers - the number of buffers to add to the queue
  1866. Return Value:
  1867. none
  1868. --*/
  1869. {
  1870. PMDL pMdl;
  1871. ULONG lBufferSize;
  1872. PVOID pBuffer;
  1873. *ppMdl = NULL;
  1874. if (NbtConfig.iCurrentNumBuff[eBuffType] >= NbtConfig.iMaxNumBuff[eBuffType])
  1875. {
  1876. return;
  1877. }
  1878. lBufferSize = NbtConfig.iBufferSize[eBuffType];
  1879. pBuffer = NbtAllocMem((USHORT)lBufferSize,NBT_TAG('g'));
  1880. if (!pBuffer)
  1881. {
  1882. return;
  1883. }
  1884. // allocate a MDL to hold the session hdr
  1885. pMdl = IoAllocateMdl(
  1886. (PVOID)pBuffer,
  1887. lBufferSize,
  1888. FALSE, // want this to be a Primary buffer - the first in the chain
  1889. FALSE,
  1890. NULL);
  1891. if (!pMdl)
  1892. {
  1893. CTEMemFree(pBuffer);
  1894. return;
  1895. }
  1896. // fill in part of the session hdr since it is always the same
  1897. if (eBuffType == eNBT_FREE_SESSION_MDLS)
  1898. {
  1899. ((tSESSIONHDR *)pBuffer)->Flags = NBT_SESSION_FLAGS;
  1900. ((tSESSIONHDR *)pBuffer)->Type = NBT_SESSION_MESSAGE;
  1901. }
  1902. // map the Mdl properly to fill in the pages portion of the MDL
  1903. MmBuildMdlForNonPagedPool(pMdl);
  1904. NbtConfig.iCurrentNumBuff[eBuffType]++;
  1905. *ppMdl = pMdl;
  1906. }
  1907. //----------------------------------------------------------------------------
  1908. NTSTATUS
  1909. NbtInitMdlQ(
  1910. PSINGLE_LIST_ENTRY pListHead,
  1911. enum eBUFFER_TYPES eBuffType)
  1912. /*++
  1913. Routine Description:
  1914. This routine allocates Mdls for use later.
  1915. Arguments:
  1916. ppListHead - a ptr to a ptr to the list head to add buffer to
  1917. iNumBuffers - the number of buffers to add to the queue
  1918. Return Value:
  1919. none
  1920. --*/
  1921. {
  1922. int i;
  1923. PMDL pMdl;
  1924. CTEPagedCode();
  1925. // Initialize the list head, so the last element always points to NULL
  1926. pListHead->Next = NULL;
  1927. // create a small number first and then lis the list grow with time
  1928. for (i=0;i < NBT_INITIAL_NUM ;i++ )
  1929. {
  1930. NbtGetMdl (&pMdl,eBuffType);
  1931. if (!pMdl)
  1932. {
  1933. KdPrint(("NBT:Unable to allocate MDL at initialization time!!\n"));\
  1934. return(STATUS_INSUFFICIENT_RESOURCES);
  1935. }
  1936. // put on free list
  1937. PushEntryList (pListHead, (PSINGLE_LIST_ENTRY)pMdl);
  1938. }
  1939. return(STATUS_SUCCESS);
  1940. }
  1941. //----------------------------------------------------------------------------
  1942. NTSTATUS
  1943. NTZwCloseFile(
  1944. IN HANDLE Handle
  1945. )
  1946. /*++
  1947. Routine Description:
  1948. This Routine handles closing a handle with NT within the context of NBT's
  1949. file system process.
  1950. Arguments:
  1951. pIrp - a ptr to an IRP
  1952. Return Value:
  1953. NTSTATUS - status of the request
  1954. --*/
  1955. {
  1956. NTSTATUS status;
  1957. BOOLEAN Attached = FALSE;
  1958. CTEPagedCode();
  1959. //
  1960. // Attach to NBT's FSP (file system process) to free the handle since
  1961. // the handle is only valid in that process.
  1962. //
  1963. CTEAttachFsp(&Attached, REF_FSP_CLOSE_FILE);
  1964. status = ZwClose(Handle);
  1965. CTEDetachFsp(Attached, REF_FSP_CLOSE_FILE);
  1966. return(status);
  1967. }
  1968. //----------------------------------------------------------------------------
  1969. NTSTATUS
  1970. NTReReadRegistry(
  1971. IN tDEVICECONTEXT * pDeviceContext,
  1972. IN BOOL bDoRefresh
  1973. )
  1974. /*++
  1975. Routine Description:
  1976. This Routine re-reads the registry values when DHCP issues the Ioctl
  1977. to do so.
  1978. Arguments:
  1979. pIrp - a ptr to an IRP
  1980. Return Value:
  1981. NTSTATUS - status of the request
  1982. --*/
  1983. {
  1984. tADDRARRAY DeviceAddressArray;
  1985. PLIST_ENTRY pHead;
  1986. PLIST_ENTRY pEntry;
  1987. #ifdef MULTIPLE_WINS
  1988. int j;
  1989. #endif
  1990. CTEPagedCode();
  1991. ASSERT (NBT_VERIFY_HANDLE2 (pDeviceContext, NBT_VERIFY_DEVCONTEXT, NBT_VERIFY_DEVCONTEXT_DOWN));
  1992. IF_DBG(NBT_DEBUG_NAMESRV)
  1993. KdPrint(("NBT:Found BindName: %lx\n", pDeviceContext->BindName));
  1994. if (LookupDeviceInRegistry(&pDeviceContext->BindName, &DeviceAddressArray, NULL) == STATUS_SUCCESS) {
  1995. //
  1996. // We found a match
  1997. //
  1998. pDeviceContext->lNameServerAddress = DeviceAddressArray.NameServerAddress;
  1999. pDeviceContext->lBackupServer = DeviceAddressArray.BackupServer;
  2000. pDeviceContext->SwitchedToBackup = 0;
  2001. pDeviceContext->RefreshToBackup = 0;
  2002. #ifdef MULTIPLE_WINS
  2003. pDeviceContext->lNumOtherServers = DeviceAddressArray.NumOtherServers;
  2004. pDeviceContext->lLastResponsive = 0;
  2005. for (j = 0; j < DeviceAddressArray.NumOtherServers; j++) {
  2006. pDeviceContext->lOtherServers[j] = DeviceAddressArray.Others[j];
  2007. }
  2008. #endif
  2009. #ifdef _NETBIOSLESS
  2010. pDeviceContext->NetbiosEnabled = DeviceAddressArray.NetbiosEnabled;
  2011. IF_DBG(NBT_DEBUG_NAMESRV)
  2012. KdPrint(("Nbt.NTReReadRegistry: <%wZ> NetbiosEnabled=<%d>\n",
  2013. &pDeviceContext->ExportName, pDeviceContext->NetbiosEnabled));
  2014. #endif
  2015. pDeviceContext->RasProxyFlags = DeviceAddressArray.RasProxyFlags;
  2016. pDeviceContext->EnableNagling = DeviceAddressArray.EnableNagling;
  2017. SetNodeType();
  2018. } else {
  2019. KdPrint(("netbt!NtReReadRegistry: Cannot find device in the registry\n"));
  2020. }
  2021. if (pDeviceContext->IpAddress)
  2022. {
  2023. if (!(NodeType & BNODE))
  2024. {
  2025. if (bDoRefresh) {
  2026. // Probably the Ip address just changed and Dhcp is informing us
  2027. // of a new Wins Server addresses, so refresh all the names to the
  2028. // new wins server
  2029. //
  2030. ReRegisterLocalNames(pDeviceContext, FALSE);
  2031. }
  2032. }
  2033. else
  2034. {
  2035. //
  2036. // no need to refresh
  2037. // on a Bnode
  2038. //
  2039. NbtStopRefreshTimer();
  2040. }
  2041. }
  2042. return(STATUS_SUCCESS);
  2043. }
  2044. //----------------------------------------------------------------------------
  2045. ULONG EventLogSequenceNumber = 0;
  2046. NTSTATUS
  2047. NbtLogEventDetailed(
  2048. IN ULONG EventCode,
  2049. IN NTSTATUS NtStatusCode,
  2050. IN ULONG Info,
  2051. IN PVOID RawDataBuffer,
  2052. IN USHORT RawDataLength,
  2053. IN USHORT NumberOfInsertionStrings,
  2054. ...
  2055. )
  2056. #define LAST_NAMED_ARGUMENT NumberOfInsertionStrings
  2057. /*++
  2058. Routine Description:
  2059. This function allocates an I/O error log record, fills it in and writes it
  2060. to the I/O error log.
  2061. Arguments:
  2062. Return Value:
  2063. None.
  2064. --*/
  2065. {
  2066. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  2067. va_list ParmPtr; // Pointer to stack parms.
  2068. PCHAR DumpData;
  2069. LONG Length;
  2070. ULONG i, SizeOfRawData, RemainingSpace, TotalErrorLogEntryLength;
  2071. ULONG SizeOfStringData = 0;
  2072. PWSTR StringOffset, InsertionString;
  2073. if (NumberOfInsertionStrings != 0)
  2074. {
  2075. va_start (ParmPtr, LAST_NAMED_ARGUMENT);
  2076. for (i = 0; i < NumberOfInsertionStrings; i += 1)
  2077. {
  2078. InsertionString = va_arg (ParmPtr, PWSTR);
  2079. Length = wcslen (InsertionString);
  2080. while ((Length > 0) && (InsertionString[Length-1] == L' '))
  2081. {
  2082. Length--;
  2083. }
  2084. SizeOfStringData += (Length + 1) * sizeof(WCHAR);
  2085. }
  2086. }
  2087. //
  2088. // Ideally we want the packet to hold the servername and ExtraInformation.
  2089. // Usually the ExtraInformation gets truncated.
  2090. //
  2091. TotalErrorLogEntryLength = min (RawDataLength + sizeof(IO_ERROR_LOG_PACKET) + 1 + SizeOfStringData,
  2092. ERROR_LOG_MAXIMUM_SIZE);
  2093. RemainingSpace = TotalErrorLogEntryLength - FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData);
  2094. if (RemainingSpace > SizeOfStringData)
  2095. {
  2096. SizeOfRawData = RemainingSpace - SizeOfStringData;
  2097. }
  2098. else
  2099. {
  2100. SizeOfStringData = RemainingSpace;
  2101. SizeOfRawData = 0;
  2102. }
  2103. ErrorLogEntry = IoAllocateErrorLogEntry (NbtConfig.DriverObject, (UCHAR) TotalErrorLogEntryLength);
  2104. if (ErrorLogEntry == NULL)
  2105. {
  2106. IF_DBG(NBT_DEBUG_NAMESRV)
  2107. KdPrint(("Nbt: Unable to allocate Error Packet for Error logging\n"));
  2108. return(STATUS_INSUFFICIENT_RESOURCES);
  2109. }
  2110. //
  2111. // Fill in the error log entry
  2112. //
  2113. ErrorLogEntry->ErrorCode = EventCode;
  2114. ErrorLogEntry->UniqueErrorValue = Info;
  2115. ErrorLogEntry->FinalStatus = NtStatusCode;
  2116. ErrorLogEntry->MajorFunctionCode = 0;
  2117. ErrorLogEntry->RetryCount = 0;
  2118. ErrorLogEntry->IoControlCode = 0;
  2119. ErrorLogEntry->DeviceOffset.LowPart = 0;
  2120. ErrorLogEntry->DeviceOffset.HighPart = 0;
  2121. ErrorLogEntry->DumpDataSize = 0;
  2122. ErrorLogEntry->NumberOfStrings = 0;
  2123. ErrorLogEntry->SequenceNumber = EventLogSequenceNumber++;
  2124. ErrorLogEntry->StringOffset = (USHORT) (ROUND_UP_COUNT (FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  2125. + SizeOfRawData, ALIGN_WORD));
  2126. //
  2127. // Append the dump data. This information is typically an SMB header.
  2128. //
  2129. if ((RawDataBuffer) && (SizeOfRawData))
  2130. {
  2131. DumpData = (PCHAR) ErrorLogEntry->DumpData;
  2132. Length = min (RawDataLength, (USHORT)SizeOfRawData);
  2133. RtlCopyMemory (DumpData, RawDataBuffer, Length);
  2134. ErrorLogEntry->DumpDataSize = (USHORT)Length;
  2135. }
  2136. //
  2137. // Add the debug informatuion strings
  2138. //
  2139. if (NumberOfInsertionStrings)
  2140. {
  2141. StringOffset = (PWSTR) ((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  2142. //
  2143. // Set up ParmPtr to point to first of the caller's parameters.
  2144. //
  2145. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  2146. for (i = 0 ; i < NumberOfInsertionStrings ; i+= 1)
  2147. {
  2148. InsertionString = va_arg(ParmPtr, PWSTR);
  2149. Length = wcslen(InsertionString);
  2150. while ( (Length > 0) && (InsertionString[Length-1] == L' '))
  2151. {
  2152. Length--;
  2153. }
  2154. if (((Length + 1) * sizeof(WCHAR)) > SizeOfStringData)
  2155. {
  2156. Length = (SizeOfStringData/sizeof(WCHAR)) - 1;
  2157. }
  2158. if (Length > 0)
  2159. {
  2160. RtlCopyMemory (StringOffset, InsertionString, Length*sizeof(WCHAR));
  2161. StringOffset += Length;
  2162. *StringOffset++ = L'\0';
  2163. SizeOfStringData -= (Length + 1) * sizeof(WCHAR);
  2164. ErrorLogEntry->NumberOfStrings += 1;
  2165. }
  2166. }
  2167. }
  2168. IoWriteErrorLogEntry(ErrorLogEntry);
  2169. return(STATUS_SUCCESS);
  2170. }
  2171. NTSTATUS
  2172. NbtLogEvent(
  2173. IN ULONG EventCode,
  2174. IN NTSTATUS Status,
  2175. IN ULONG Location
  2176. )
  2177. /*++
  2178. Routine Description:
  2179. This function allocates an I/O error log record, fills it in and writes it
  2180. to the I/O error log.
  2181. Arguments:
  2182. EventCode - Identifies the error message.
  2183. Status - The status value to log: this value is put into the
  2184. data portion of the log message.
  2185. Return Value:
  2186. STATUS_SUCCESS - The error was successfully logged..
  2187. STATUS_BUFER_OVERFLOW - The error data was too large to be logged.
  2188. STATUS_INSUFFICIENT_RESOURCES - Unable to allocate memory.
  2189. --*/
  2190. {
  2191. return (NbtLogEventDetailed (EventCode, Status, Location, NULL, 0, 0));
  2192. }
  2193. VOID
  2194. DelayedNbtLogDuplicateNameEvent(
  2195. IN PVOID Context1,
  2196. IN PVOID Context2,
  2197. IN PVOID Context3,
  2198. IN tDEVICECONTEXT *pDeviceContext
  2199. )
  2200. {
  2201. tNAMEADDR *pNameAddr = (tNAMEADDR *) Context1;
  2202. tIPADDRESS RemoteIpAddress = (tIPADDRESS) PtrToUlong (Context2);
  2203. ULONG Location = (ULONG) PtrToUlong (Context3);
  2204. UCHAR *pszNameOrig = pNameAddr->Name;
  2205. NTSTATUS status;
  2206. UCHAR *pAddr;
  2207. WCHAR wstrName[22];
  2208. WCHAR wstrDeviceIp[22];
  2209. WCHAR wstrRemoteServerIp[22];
  2210. UCHAR pszName[22];
  2211. STRING TmpOEMString;
  2212. UNICODE_STRING UnicodeString;
  2213. CTEPagedCode();
  2214. UnicodeString.MaximumLength = sizeof(WCHAR)*(22);
  2215. sprintf (pszName,"%-15.15s:%x", pszNameOrig, pszNameOrig[15]);
  2216. UnicodeString.Length = 0;
  2217. UnicodeString.Buffer = wstrName;
  2218. RtlInitString (&TmpOEMString, pszName);
  2219. status = RtlOemStringToUnicodeString (&UnicodeString, &TmpOEMString, FALSE);
  2220. UnicodeString.Buffer[UnicodeString.Length/sizeof(WCHAR)] = L'\0';
  2221. pAddr = (PUCHAR) &pDeviceContext->IpAddress;
  2222. swprintf (wstrDeviceIp, L"%d.%d.%d.%d", pAddr[3], pAddr[2], pAddr[1], pAddr[0]);
  2223. pAddr = (PUCHAR) &RemoteIpAddress;
  2224. swprintf (wstrRemoteServerIp, L"%d.%d.%d.%d", pAddr[3], pAddr[2], pAddr[1], pAddr[0]);
  2225. status = NbtLogEventDetailed (EVENT_NBT_DUPLICATE_NAME_ERROR,
  2226. STATUS_UNSUCCESSFUL,
  2227. Location,
  2228. NULL,
  2229. 0,
  2230. 3,
  2231. &wstrName,
  2232. &wstrDeviceIp,
  2233. &wstrRemoteServerIp);
  2234. NBT_DEREFERENCE_NAMEADDR (pNameAddr, REF_NAME_LOG_EVENT, FALSE);
  2235. }
  2236. #if DBG
  2237. //----------------------------------------------------------------------------
  2238. VOID
  2239. AcquireSpinLockDebug(
  2240. IN tNBT_LOCK_INFO *pLockInfo,
  2241. IN PKIRQL pOldIrq,
  2242. IN INT LineNumber
  2243. )
  2244. /*++
  2245. Routine Description:
  2246. This function gets the spin lock, and then sets the mask in Nbtconfig, per
  2247. processor.
  2248. Arguments:
  2249. Return Value:
  2250. --*/
  2251. {
  2252. CCHAR CurrProc;
  2253. UCHAR LockFree;
  2254. CTEGetLock(&pLockInfo->SpinLock,pOldIrq);
  2255. CurrProc = (CCHAR)KeGetCurrentProcessorNumber();
  2256. NbtConfig.CurrProc = CurrProc;
  2257. LockFree = (pLockInfo->LockNumber > (UCHAR)NbtConfig.CurrentLockNumber[CurrProc]);
  2258. if (!LockFree)
  2259. {
  2260. KdPrint(("Nbt.AcquireSpinLockDebug: CurrProc = %X, CurrentLockNum = %X DataSTructLock = %X\n",
  2261. CurrProc,NbtConfig.CurrentLockNumber[CurrProc],pLockInfo->LockNumber));
  2262. } \
  2263. ASSERTMSG("Possible DeadLock, Getting SpinLock at a lower level\n",LockFree);
  2264. NbtConfig.CurrentLockNumber[CurrProc]|= pLockInfo->LockNumber;
  2265. pLockInfo->LastLockLine = LineNumber;
  2266. }
  2267. //----------------------------------------------------------------------------
  2268. VOID
  2269. FreeSpinLockDebug(
  2270. IN tNBT_LOCK_INFO *pLockInfo,
  2271. IN KIRQL OldIrq,
  2272. IN INT LineNumber
  2273. )
  2274. /*++
  2275. Routine Description:
  2276. This function clears the spin lock from the mask in Nbtconfig, per
  2277. processor and then releases the spin lock.
  2278. Arguments:
  2279. Return Value:
  2280. none
  2281. --*/
  2282. {
  2283. CCHAR CurrProc;
  2284. CurrProc = (CCHAR)KeGetCurrentProcessorNumber();
  2285. NbtConfig.CurrentLockNumber[CurrProc] &= ~pLockInfo->LockNumber;
  2286. pLockInfo->LastReleaseLine = LineNumber;
  2287. CTEFreeLock(&pLockInfo->SpinLock,OldIrq);
  2288. }
  2289. //----------------------------------------------------------------------------
  2290. VOID
  2291. AcquireSpinLockAtDpcDebug(
  2292. IN tNBT_LOCK_INFO *pLockInfo,
  2293. IN INT LineNumber
  2294. )
  2295. /*++
  2296. Routine Description:
  2297. This function gets the spin lock, and then sets the mask in Nbtconfig, per
  2298. processor.
  2299. Arguments:
  2300. Return Value:
  2301. --*/
  2302. {
  2303. CCHAR CurrProc;
  2304. UCHAR LockFree;
  2305. CTEGetLockAtDPC(&pLockInfo->SpinLock);
  2306. pLockInfo->LastLockLine = LineNumber;
  2307. CurrProc = (CCHAR)KeGetCurrentProcessorNumber();
  2308. NbtConfig.CurrProc = CurrProc;
  2309. LockFree = (pLockInfo->LockNumber > (UCHAR)NbtConfig.CurrentLockNumber[CurrProc]);
  2310. if (!LockFree)
  2311. {
  2312. KdPrint(("Nbt.AcquireSpinLockAtDpcDebug: CurrProc = %X, CurrentLockNum = %X DataSTructLock = %X\n",
  2313. CurrProc,NbtConfig.CurrentLockNumber[CurrProc],pLockInfo->LockNumber));
  2314. } \
  2315. ASSERTMSG("Possible DeadLock, Getting SpinLock at a lower level\n",LockFree);
  2316. NbtConfig.CurrentLockNumber[CurrProc]|= pLockInfo->LockNumber;
  2317. }
  2318. //----------------------------------------------------------------------------
  2319. VOID
  2320. FreeSpinLockAtDpcDebug(
  2321. IN tNBT_LOCK_INFO *pLockInfo,
  2322. IN INT LineNumber
  2323. )
  2324. /*++
  2325. Routine Description:
  2326. This function clears the spin lock from the mask in Nbtconfig, per
  2327. processor and then releases the spin lock.
  2328. Arguments:
  2329. Return Value:
  2330. none
  2331. --*/
  2332. {
  2333. CCHAR CurrProc;
  2334. CurrProc = (CCHAR)KeGetCurrentProcessorNumber();
  2335. NbtConfig.CurrentLockNumber[CurrProc] &= ~pLockInfo->LockNumber;
  2336. pLockInfo->LastReleaseLine = LineNumber;
  2337. CTEFreeLockFromDPC(&pLockInfo->SpinLock);
  2338. }
  2339. #endif //if Dbg
  2340. NTSTATUS
  2341. NbtBuildDeviceAcl(
  2342. OUT PACL * DeviceAcl
  2343. )
  2344. /*++
  2345. Routine Description:
  2346. (Lifted from TCP - TcpBuildDeviceAcl)
  2347. This routine builds an ACL which gives Administrators, LocalService and NetworkService
  2348. principals full access. All other principals have no access.
  2349. Arguments:
  2350. DeviceAcl - Output pointer to the new ACL.
  2351. Return Value:
  2352. STATUS_SUCCESS or an appropriate error code.
  2353. --*/
  2354. {
  2355. PGENERIC_MAPPING GenericMapping;
  2356. PSID AdminsSid, ServiceSid, NetworkSid;
  2357. ULONG AclLength;
  2358. NTSTATUS Status;
  2359. ACCESS_MASK AccessMask = GENERIC_ALL;
  2360. PACL NewAcl;
  2361. //
  2362. // Enable access to all the globally defined SIDs
  2363. //
  2364. GenericMapping = IoGetFileObjectGenericMapping();
  2365. RtlMapGenericMask(&AccessMask, GenericMapping);
  2366. AdminsSid = SeExports->SeAliasAdminsSid;
  2367. ServiceSid = SeExports->SeLocalServiceSid;
  2368. NetworkSid = SeExports->SeNetworkServiceSid;
  2369. AclLength = sizeof(ACL) +
  2370. 3 * sizeof(ACCESS_ALLOWED_ACE) +
  2371. RtlLengthSid(AdminsSid) +
  2372. RtlLengthSid(ServiceSid) +
  2373. RtlLengthSid(NetworkSid) -
  2374. 3 * sizeof(ULONG);
  2375. NewAcl = ExAllocatePool(PagedPool, AclLength);
  2376. if (NewAcl == NULL) {
  2377. return (STATUS_INSUFFICIENT_RESOURCES);
  2378. }
  2379. Status = RtlCreateAcl(NewAcl, AclLength, ACL_REVISION);
  2380. if (!NT_SUCCESS(Status)) {
  2381. ExFreePool(NewAcl);
  2382. return (Status);
  2383. }
  2384. Status = RtlAddAccessAllowedAce(
  2385. NewAcl,
  2386. ACL_REVISION2,
  2387. AccessMask,
  2388. AdminsSid
  2389. );
  2390. ASSERT(NT_SUCCESS(Status));
  2391. if (!NT_SUCCESS(Status)) {
  2392. ExFreePool(NewAcl);
  2393. return (Status);
  2394. }
  2395. Status = RtlAddAccessAllowedAce(
  2396. NewAcl,
  2397. ACL_REVISION2,
  2398. AccessMask,
  2399. ServiceSid
  2400. );
  2401. ASSERT(NT_SUCCESS(Status));
  2402. if (!NT_SUCCESS(Status)) {
  2403. ExFreePool(NewAcl);
  2404. return (Status);
  2405. }
  2406. Status = RtlAddAccessAllowedAce(
  2407. NewAcl,
  2408. ACL_REVISION2,
  2409. AccessMask,
  2410. NetworkSid
  2411. );
  2412. ASSERT(NT_SUCCESS(Status));
  2413. if (!NT_SUCCESS(Status)) {
  2414. ExFreePool(NewAcl);
  2415. return (Status);
  2416. }
  2417. *DeviceAcl = NewAcl;
  2418. return (STATUS_SUCCESS);
  2419. }
  2420. NTSTATUS
  2421. NbtCreateAdminSecurityDescriptor(PDEVICE_OBJECT dev)
  2422. /*++
  2423. Routine Description:
  2424. (Lifted from TCP - TcpCreateAdminSecurityDescriptor)
  2425. This routine creates a security descriptor which gives access
  2426. only to Administrtors and LocalService. This descriptor is used
  2427. to access check raw endpoint opens and exclisive access to transport
  2428. addresses.
  2429. Arguments:
  2430. None.
  2431. Return Value:
  2432. STATUS_SUCCESS or an appropriate error code.
  2433. --*/
  2434. {
  2435. PACL rawAcl = NULL;
  2436. NTSTATUS status;
  2437. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  2438. PSECURITY_DESCRIPTOR localSecurityDescriptor = (PSECURITY_DESCRIPTOR) & buffer;
  2439. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  2440. //
  2441. // Build a local security descriptor with an ACL giving only
  2442. // administrators and service access.
  2443. //
  2444. status = NbtBuildDeviceAcl(&rawAcl);
  2445. if (!NT_SUCCESS(status)) {
  2446. KdPrint(("TCP: Unable to create Raw ACL, error: %x\n", status));
  2447. return (status);
  2448. }
  2449. (VOID) RtlCreateSecurityDescriptor(
  2450. localSecurityDescriptor,
  2451. SECURITY_DESCRIPTOR_REVISION
  2452. );
  2453. (VOID) RtlSetDaclSecurityDescriptor(
  2454. localSecurityDescriptor,
  2455. TRUE,
  2456. rawAcl,
  2457. FALSE
  2458. );
  2459. //
  2460. // Now apply the local descriptor to the raw descriptor.
  2461. //
  2462. status = SeSetSecurityDescriptorInfo(
  2463. NULL,
  2464. &securityInformation,
  2465. localSecurityDescriptor,
  2466. &dev->SecurityDescriptor,
  2467. PagedPool,
  2468. IoGetFileObjectGenericMapping()
  2469. );
  2470. if (!NT_SUCCESS(status)) {
  2471. KdPrint(("Nbt: SeSetSecurity failed, %lx\n", status));
  2472. }
  2473. ExFreePool(rawAcl);
  2474. return (status);
  2475. }