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.

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