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.

1866 lines
66 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. NTPNP.c
  5. Abstract:
  6. This module implements the DRIVER_INITIALIZATION routine for the
  7. NBT Transport and other routines that are specific to the NT implementation
  8. of a driver.
  9. Author:
  10. Earle R. Horton (earleh) 08-Nov-1995
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "ntddip.h" // Needed for PNETBT_PNP_RECONFIG_REQUEST
  15. #include "ntprocs.h"
  16. #include <tcpinfo.h>
  17. #include <tdiinfo.h>
  18. #include "ntpnp.tmh"
  19. #ifdef _NETBIOSLESS
  20. NTSTATUS
  21. NbtSpecialDeviceAdd(
  22. PUNICODE_STRING pucBindName,
  23. PUNICODE_STRING pucExportName,
  24. PWSTR pKeyName,
  25. USHORT DefaultSessionPort,
  26. USHORT DefaultDatagramPort
  27. );
  28. NTSTATUS
  29. NbtSpecialReadRegistry(
  30. PWSTR pKeyName,
  31. tDEVICECONTEXT *pDeviceContext,
  32. USHORT DefaultSessionPort,
  33. USHORT DefaultDatagramPort
  34. );
  35. #endif
  36. tDEVICECONTEXT *
  37. CheckAddrNotification(
  38. IN PTA_ADDRESS Addr,
  39. IN PUNICODE_STRING pDeviceName,
  40. OUT ULONG* IpAddr
  41. );
  42. extern HANDLE TdiClientHandle;
  43. extern HANDLE TdiProviderHandle;
  44. DWORD AddressCount = 0;
  45. NET_DEVICE_POWER_STATE LastSystemPowerState = NetDeviceStateD0; // by default
  46. //******************* Pageable Routine Declarations ****************
  47. #ifdef ALLOC_PRAGMA
  48. #pragma CTEMakePageable(PAGE, NbtNotifyTdiClients)
  49. #pragma CTEMakePageable(PAGE, NbtAddressAdd)
  50. #pragma CTEMakePageable(PAGE, NbtAddNewInterface)
  51. #pragma CTEMakePageable(PAGE, NbtDeviceAdd)
  52. #pragma CTEMakePageable(PAGE, TdiAddressArrival)
  53. #pragma CTEMakePageable(PAGE, TdiAddressDeletion)
  54. #pragma CTEMakePageable(PAGE, TdiBindHandler)
  55. #pragma CTEMakePageable(PAGE, NbtCreateSmbDevice)
  56. #pragma CTEMakePageable(PAGE, NbtSpecialReadRegistry)
  57. #pragma CTEMakePageable(PAGE, NbtPnPPowerComplete)
  58. #pragma CTEMakePageable(PAGE, TdiPnPPowerHandler)
  59. #pragma CTEMakePageable(PAGE, LookupDeviceInRegistry)
  60. #pragma CTEMakePageable(PAGE, CheckAddrNotification)
  61. #endif
  62. //******************* Pageable Routine Declarations ****************
  63. //
  64. // This used at the boot time.
  65. // We shouldn't call TdiProviderReady until all the interfaces
  66. // we know so far have been initialized
  67. //
  68. // TcpipReady: set to TRUE when we receive TdiProviderReady from IP
  69. // NumIfBeingIndicated: the # of interfaces being indicated to our clients
  70. // JustBooted: set to FALSE after we call TdiProviderReady
  71. //
  72. DWORD JustBooted = TRUE;
  73. #define IsBootTime() (InterlockedExchange(&JustBooted, FALSE))
  74. //#if DBG
  75. //
  76. // TcpipReady is for debugging purpose only.
  77. //
  78. // BootTimeCounter is initialized to ONE which
  79. // take it into account.
  80. //
  81. int TcpipReady = FALSE;
  82. //#endif
  83. LONG BootTimeCounter = 1; // For the IP's ProviderReady
  84. void
  85. NbtUpBootCounter(void)
  86. {
  87. if (!JustBooted) {
  88. return;
  89. }
  90. ASSERT(BootTimeCounter >= 0);
  91. InterlockedIncrement(&BootTimeCounter);
  92. }
  93. void
  94. NbtDownBootCounter(void)
  95. {
  96. LONG CounterSnapshot;
  97. if (!JustBooted) {
  98. return;
  99. }
  100. ASSERT(BootTimeCounter > 0);
  101. CounterSnapshot = InterlockedDecrement(&BootTimeCounter);
  102. if (!CounterSnapshot && IsBootTime()) {
  103. //
  104. // Just try our best
  105. //
  106. // The caller always call us at PASSIVE_LEVEL except from
  107. // StartProcessNbtDhcpRequests, a timer routine which could
  108. // be called at DISPATCH_LEVEL
  109. //
  110. if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
  111. TdiProviderReady (TdiProviderHandle); // Notify our clients now
  112. } else {
  113. //
  114. // Although this is a benign assert, we still want it
  115. // to capture the normal cases in which this function
  116. // should be called at PASSIVE_LEVEL.
  117. //
  118. ASSERT (0);
  119. }
  120. }
  121. }
  122. static
  123. IsIPv6Interface(
  124. PUNICODE_STRING pDeviceName
  125. )
  126. {
  127. return (pDeviceName->Length >= 28 && pDeviceName->Buffer[13] == '6');
  128. }
  129. //----------------------------------------------------------------------------
  130. tDEVICECONTEXT *
  131. NbtFindAndReferenceDevice(
  132. PUNICODE_STRING pucBindName,
  133. BOOLEAN fNameIsBindName
  134. )
  135. {
  136. PLIST_ENTRY pHead;
  137. PLIST_ENTRY pEntry;
  138. tDEVICECONTEXT *pDeviceContext;
  139. CTELockHandle OldIrq;
  140. PUNICODE_STRING pucNameToCompare;
  141. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  142. pHead = &NbtConfig.DeviceContexts;
  143. pEntry = pHead->Flink;
  144. while (pEntry != pHead)
  145. {
  146. pDeviceContext = CONTAINING_RECORD(pEntry,tDEVICECONTEXT,Linkage);
  147. //
  148. // Reference this device so that it doesn't disappear when we release the lock!
  149. //
  150. NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  151. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  152. //
  153. // Set the right type of name to compare against
  154. //
  155. if (fNameIsBindName)
  156. {
  157. pucNameToCompare = &pDeviceContext->BindName;
  158. }
  159. else
  160. {
  161. pucNameToCompare = &pDeviceContext->ExportName;
  162. }
  163. //
  164. // Use case-insensitive compare since registry is case-insensitive
  165. //
  166. if (RtlCompareUnicodeString(pucBindName, pucNameToCompare, TRUE) == 0)
  167. {
  168. //
  169. // We have already Referenced this device above
  170. //
  171. return (pDeviceContext);
  172. }
  173. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  174. pEntry = pEntry->Flink;
  175. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE);
  176. }
  177. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  178. return (tDEVICECONTEXT *)NULL;
  179. }
  180. VOID
  181. NbtNotifyTdiClients(
  182. IN tDEVICECONTEXT *pDeviceContext,
  183. IN enum eTDI_ACTION Action
  184. )
  185. /*++
  186. Routine Description:
  187. This is where all Tdi registrations and Deregistrations occur
  188. ASSUMPTION: Only 1 thread will running this request at any time
  189. Arguments:
  190. None.
  191. Return Value:
  192. None (since this is a Worker thread)
  193. --*/
  194. {
  195. CTELockHandle OldIrq;
  196. NTSTATUS status = STATUS_SUCCESS;
  197. HANDLE NetAddressRegistrationHandle, DeviceRegistrationHandle;
  198. PLIST_ENTRY pEntry;
  199. CTEPagedCode();
  200. NbtTrace(NBT_TRACE_PNP, ("ExportName=%Z BindName=%Z Action=%d",
  201. &pDeviceContext->ExportName, &pDeviceContext->BindName, Action));
  202. switch (Action)
  203. {
  204. case NBT_TDI_REGISTER:
  205. {
  206. //
  207. // Add the "permanent" name to the local name table. This is the IP
  208. // address of the node padded out to 16 bytes with zeros.
  209. //
  210. #ifdef _NETBIOSLESS
  211. if (!IsDeviceNetbiosless(pDeviceContext))
  212. #endif
  213. {
  214. NbtAddPermanentName(pDeviceContext);
  215. }
  216. //
  217. // If the device was not registered with TDI, do so now.
  218. //
  219. if (!pDeviceContext->DeviceRegistrationHandle)
  220. {
  221. IF_DBG(NBT_DEBUG_PNP_POWER)
  222. KdPrint (("Nbt.NbtNotifyTdiClients: Calling TdiRegisterDeviceObject ...\n"));
  223. status = TdiRegisterDeviceObject( &pDeviceContext->ExportName,
  224. &pDeviceContext->DeviceRegistrationHandle);
  225. if (!NT_SUCCESS(status))
  226. {
  227. pDeviceContext->DeviceRegistrationHandle = NULL;
  228. }
  229. NbtTrace(NBT_TRACE_PNP, ("RegisterDeviceObject: ExportName=%Z BindName=%Z status=%!status!",
  230. &pDeviceContext->ExportName, &pDeviceContext->BindName, status));
  231. IF_DBG(NBT_DEBUG_PNP_POWER)
  232. KdPrint(("Nbt.NbtNotifyTdiClients: TdiRegisterDeviceObject for <%x> returned <%x>\n",
  233. pDeviceContext, status));
  234. }
  235. //
  236. // If the Net address was not registered with TDI, do so now.
  237. //
  238. if ((!pDeviceContext->NetAddressRegistrationHandle) &&
  239. #ifdef _NETBIOSLESS
  240. (!IsDeviceNetbiosless(pDeviceContext)) &&
  241. #endif
  242. (pDeviceContext->pPermClient))
  243. {
  244. TA_NETBIOS_ADDRESS PermAddress;
  245. PermAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_NETBIOS);
  246. PermAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  247. PermAddress.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  248. CTEMemCopy( PermAddress.Address[0].Address[0].NetbiosName,
  249. pDeviceContext->pPermClient->pAddress->pNameAddr->Name,
  250. NETBIOS_NAME_SIZE);
  251. status = TdiRegisterNetAddress(
  252. (PTA_ADDRESS) PermAddress.Address,
  253. &pDeviceContext->ExportName,
  254. (PTDI_PNP_CONTEXT) &pDeviceContext->Context2,
  255. &pDeviceContext->NetAddressRegistrationHandle);
  256. if (!NT_SUCCESS(status))
  257. {
  258. pDeviceContext->NetAddressRegistrationHandle = NULL;
  259. }
  260. NbtTrace(NBT_TRACE_PNP, ("RegisterNetAddress: ExportName=%Z BindName=%Z status=%!status!",
  261. &pDeviceContext->ExportName, &pDeviceContext->BindName, status));
  262. IF_DBG(NBT_DEBUG_PNP_POWER)
  263. KdPrint (("Nbt.NbtNotifyTdiClients: TdiRegisterNetAddress for <%x> returned <%x>\n",
  264. pDeviceContext, status));
  265. }
  266. break;
  267. }
  268. case NBT_TDI_DEREGISTER:
  269. {
  270. if (NetAddressRegistrationHandle = pDeviceContext->NetAddressRegistrationHandle)
  271. {
  272. pDeviceContext->NetAddressRegistrationHandle = NULL;
  273. status = TdiDeregisterNetAddress (NetAddressRegistrationHandle);
  274. NbtTrace(NBT_TRACE_PNP, ("DeregisterNetAddress: ExportName=%Z BindName=%Z status=%!status!",
  275. &pDeviceContext->ExportName, &pDeviceContext->BindName, status));
  276. IF_DBG(NBT_DEBUG_PNP_POWER)
  277. KdPrint (("Nbt.NbtNbtNotifyTdiClients: TdiDeregisterNetAddress<%x> returned<%x>\n",
  278. pDeviceContext, status));
  279. }
  280. if (DeviceRegistrationHandle = pDeviceContext->DeviceRegistrationHandle)
  281. {
  282. pDeviceContext->DeviceRegistrationHandle = NULL;
  283. status = TdiDeregisterDeviceObject (DeviceRegistrationHandle);
  284. NbtTrace(NBT_TRACE_PNP, ("DeregisterDeviceObject: ExportName=%Z BindName=%Z status=%!status!",
  285. &pDeviceContext->ExportName, &pDeviceContext->BindName, status));
  286. IF_DBG(NBT_DEBUG_PNP_POWER)
  287. KdPrint (("Nbt.NbtNotifyTdiClients: TdiDeregisterDeviceObject<%x> returned<%x>\n",
  288. pDeviceContext, status));
  289. }
  290. //
  291. // The permanent name is a function of the MAC address so remove
  292. // it since the Address is going away
  293. //
  294. #ifdef _NETBIOSLESS
  295. if (!IsDeviceNetbiosless(pDeviceContext))
  296. #endif
  297. {
  298. NbtRemovePermanentName(pDeviceContext);
  299. }
  300. break;
  301. }
  302. default:
  303. KdPrint(("Nbt.NbtNotifyTdiClients: ERROR: Invalid Action=<%x> on Device <%x>\n",
  304. Action, pDeviceContext));
  305. }
  306. }
  307. VOID
  308. NbtUpdateSmbBinding(
  309. VOID
  310. )
  311. {
  312. tDEVICECONTEXT *pSavedSmbDevice = NULL;
  313. KIRQL OldIrq = 0;
  314. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  315. if (pNbtSmbDevice && !gbDestroyingSmbDevice) {
  316. pSavedSmbDevice = pNbtSmbDevice;
  317. NBT_REFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, TRUE);
  318. }
  319. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  320. if (pSavedSmbDevice) {
  321. NETBT_SMB_BIND_REQUEST SmbRequest = { 0 };
  322. SmbRequest.RequestType = SMB_SERVER;
  323. SmbRequest.MultiSZBindList = NbtConfig.pServerBindings;
  324. SmbRequest.pDeviceName = NULL;
  325. SmbRequest.PnPOpCode = TDI_PNP_OP_ADD;
  326. if (SmbRequest.MultiSZBindList) {
  327. NbtSetSmbBindingInfo2(
  328. pSavedSmbDevice,
  329. &SmbRequest
  330. );
  331. }
  332. SmbRequest.RequestType = SMB_CLIENT;
  333. SmbRequest.MultiSZBindList = NbtConfig.pClientBindings;
  334. SmbRequest.pDeviceName = NULL;
  335. SmbRequest.PnPOpCode = TDI_PNP_OP_ADD;
  336. if (SmbRequest.MultiSZBindList) {
  337. NbtSetSmbBindingInfo2(
  338. pSavedSmbDevice,
  339. &SmbRequest
  340. );
  341. }
  342. NBT_DEREFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, FALSE);
  343. }
  344. }
  345. VOID
  346. SmbNotifyTdiClients (
  347. IN enum eTDI_ACTION Action
  348. )
  349. {
  350. tDEVICECONTEXT *pSavedSmbDevice = NULL;
  351. KIRQL OldIrq = 0;
  352. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  353. if (pNbtSmbDevice && !gbDestroyingSmbDevice) {
  354. pSavedSmbDevice = pNbtSmbDevice;
  355. NBT_REFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, TRUE);
  356. }
  357. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  358. if (pSavedSmbDevice) {
  359. NbtNotifyTdiClients (pSavedSmbDevice, Action);
  360. NBT_DEREFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, FALSE);
  361. }
  362. }
  363. //----------------------------------------------------------------------------
  364. NTSTATUS
  365. NbtAddressAdd(
  366. ULONG IpAddr,
  367. tDEVICECONTEXT *pDeviceContext,
  368. PUNICODE_STRING pucBindString
  369. )
  370. {
  371. NTSTATUS status = STATUS_SUCCESS;
  372. tADDRARRAY DeviceAddressArray;
  373. tIPADDRESS pIpAddresses[MAX_IP_ADDRS];
  374. tIPADDRESS SubnetMask;
  375. ULONG NumAddressesRead;
  376. CTEPagedCode();
  377. ASSERT(pucBindString && IpAddr);
  378. //
  379. // Find the bind and export devices to use from the device
  380. // described in the registry that uses this address.
  381. //
  382. if (status != STATUS_SUCCESS) {
  383. return status;
  384. }
  385. status = LookupDeviceInRegistry(pucBindString, &DeviceAddressArray, NULL);
  386. if (!NT_SUCCESS(status)) {
  387. KdPrint(("netbt!NbtAddressAdd: Cannot find device in the registry: status <%x>\n", status));
  388. NbtTrace(NBT_TRACE_PNP, ("BindName=%Z IP=%!ipaddr! status=%!status!",
  389. pucBindString, IpAddr, status));
  390. return STATUS_UNSUCCESSFUL;
  391. }
  392. //
  393. // Fetch a static IP address from the registry.
  394. //
  395. *pIpAddresses = 0;
  396. status = GetIPFromRegistry (pucBindString,
  397. pIpAddresses,
  398. &SubnetMask,
  399. MAX_IP_ADDRS,
  400. &NumAddressesRead,
  401. NBT_IP_STATIC);
  402. IF_DBG(NBT_DEBUG_PNP_POWER)
  403. KdPrint (("Nbt.NbtAddressAdd: GetIPFromRegistry for NBT_IP_STATIC returned <%x>\n",status));
  404. NbtTrace(NBT_TRACE_PNP, ("GetIPFromRegistry return status=%!status! for NBT_IP_STATIC BindName=%Z IP=%!ipaddr!",
  405. status, pucBindString, IpAddr));
  406. if ((status != STATUS_SUCCESS) || (*pIpAddresses != IpAddr)) {
  407. //
  408. // This one doesn't have a valid static address. Try DHCP.
  409. //
  410. *pIpAddresses = 0; // Cleanup any previously-read entries!
  411. status = GetIPFromRegistry (pucBindString,
  412. pIpAddresses,
  413. &SubnetMask,
  414. MAX_IP_ADDRS,
  415. &NumAddressesRead,
  416. NBT_IP_DHCP);
  417. IF_DBG(NBT_DEBUG_PNP_POWER)
  418. KdPrint (("Nbt.NbtAddressAdd: GetIPFromRegistry for NBT_IP_DHCP returned <%x>\n",status));
  419. NbtTrace(NBT_TRACE_PNP, ("GetIPFromRegistry return status=%!status! for NBT_IP_DHCP BindName=%Z IP=%!ipaddr!",
  420. status, pucBindString, IpAddr));
  421. }
  422. if ((status != STATUS_SUCCESS) || (*pIpAddresses != IpAddr)) {
  423. //
  424. // Check for Autoconfiguration IP address
  425. //
  426. *pIpAddresses = 0; // Cleanup any previously-read entries!
  427. status = GetIPFromRegistry (pucBindString,
  428. pIpAddresses,
  429. &SubnetMask,
  430. MAX_IP_ADDRS,
  431. &NumAddressesRead,
  432. NBT_IP_AUTOCONFIGURATION);
  433. IF_DBG(NBT_DEBUG_PNP_POWER)
  434. KdPrint (("Nbt.NbtAddressAdd: GetIPFromRegistry for NBT_IP_AUTOCONFIGURATION returned <%x>\n",
  435. status));
  436. NbtTrace(NBT_TRACE_PNP, ("GetIPFromRegistry return status=%!status! for NBT_IP_AUTO BindName=%Z IP=%!ipaddr!",
  437. status, pucBindString, IpAddr));
  438. }
  439. //
  440. // The Device must have been created beforehand by using the BindHandler
  441. //
  442. if ((status == STATUS_SUCCESS) && (*pIpAddresses == IpAddr)) {
  443. BOOLEAN IsDuplicateNotification = FALSE;
  444. #ifdef MULTIPLE_WINS
  445. int i;
  446. #endif
  447. pDeviceContext->RasProxyFlags = DeviceAddressArray.RasProxyFlags;
  448. pDeviceContext->EnableNagling = DeviceAddressArray.EnableNagling;
  449. //
  450. // Initialize the WINs server addresses
  451. //
  452. if ((IpAddr == pDeviceContext->IpAddress) &&
  453. (DeviceAddressArray.NetbiosEnabled == pDeviceContext->NetbiosEnabled))
  454. {
  455. IsDuplicateNotification = TRUE;
  456. NbtTrace(NBT_TRACE_PNP, ("Duplicate notification: %Z %!ipaddr!", pucBindString, IpAddr));
  457. }
  458. pDeviceContext->lNameServerAddress = DeviceAddressArray.NameServerAddress;
  459. pDeviceContext->lBackupServer = DeviceAddressArray.BackupServer;
  460. pDeviceContext->RefreshToBackup = 0;
  461. pDeviceContext->SwitchedToBackup = 0;
  462. #ifdef MULTIPLE_WINS
  463. pDeviceContext->lNumOtherServers = DeviceAddressArray.NumOtherServers;
  464. pDeviceContext->lLastResponsive = 0;
  465. for (i = 0; i < DeviceAddressArray.NumOtherServers; i++) {
  466. pDeviceContext->lOtherServers[i] = DeviceAddressArray.Others[i];
  467. }
  468. #endif
  469. #ifdef _NETBIOSLESS
  470. pDeviceContext->NetbiosEnabled = DeviceAddressArray.NetbiosEnabled;
  471. IF_DBG(NBT_DEBUG_PNP_POWER)
  472. KdPrint(("NbtAddressAdd: %wZ, enabled = %d\n",
  473. &pDeviceContext->ExportName, pDeviceContext->NetbiosEnabled));
  474. NbtTrace(NBT_TRACE_PNP, ("NetbiosEnabled=%x: %Z %!ipaddr!",
  475. pDeviceContext->NetbiosEnabled, pucBindString, IpAddr));
  476. #endif
  477. //
  478. // Open the addresses with the transports
  479. // these are passed into here in the reverse byte order, wrt to the IOCTL
  480. // from DHCP.
  481. //
  482. if (IsDuplicateNotification) {
  483. status = STATUS_UNSUCCESSFUL;
  484. } else {
  485. ULONG i;
  486. //
  487. // We may have read more than Ip address for this Device
  488. // so save all of them
  489. //
  490. if (NumAddressesRead > 1) {
  491. for (i=1; i<NumAddressesRead; i++) {
  492. pDeviceContext->AdditionalIpAddresses[i-1] = pIpAddresses[i];
  493. }
  494. }
  495. ASSERT (NumAddressesRead > 0);
  496. #if 0
  497. //
  498. // TcpIp does not support opening of multiple addresses
  499. // per handle, so disable this option for now!
  500. //
  501. pDeviceContext->NumAdditionalIpAddresses = NumAddressesRead - 1;
  502. #endif
  503. pDeviceContext->AssignedIpAddress = IpAddr;
  504. NbtNewDhcpAddress(pDeviceContext,htonl(*pIpAddresses),htonl(SubnetMask));
  505. NbtUpdateSmbBinding();
  506. }
  507. } else {
  508. KdPrint (("Nbt.NbtAddressAdd: ERROR -- pDeviceContext=<%x>, status=<%x>, IpAddr=<%x>, ulIpAddress=<%x>\n",
  509. pDeviceContext, status, IpAddr, *pIpAddresses));
  510. status = STATUS_UNSUCCESSFUL;
  511. }
  512. return status;
  513. }
  514. NTSTATUS
  515. NbtAddNewInterface (
  516. IN PIRP pIrp,
  517. IN PVOID *pBuffer,
  518. IN ULONG Size
  519. )
  520. /*++
  521. Routine Description:
  522. Creates a device context by coming up with a unique export string to name
  523. the device.
  524. Arguments:
  525. Return Value:
  526. Notes:
  527. --*/
  528. {
  529. ULONG nextIndex = InterlockedIncrement(&NbtConfig.InterfaceIndex);
  530. WCHAR Suffix[16];
  531. WCHAR Bind[60] = L"\\Device\\If";
  532. WCHAR Export[60] = L"\\Device\\NetBt_If";
  533. UNICODE_STRING ucSuffix;
  534. UNICODE_STRING ucBindStr;
  535. UNICODE_STRING ucExportStr;
  536. NTSTATUS status;
  537. ULONG OutSize;
  538. BOOLEAN Attached = FALSE;
  539. tADDRARRAY *pAddrArray = NULL;
  540. tDEVICECONTEXT *pDeviceContext = NULL;
  541. PNETBT_ADD_DEL_IF pAddDelIf = (PNETBT_ADD_DEL_IF)pBuffer;
  542. CTEPagedCode();
  543. //
  544. // Validate output buffer size
  545. //
  546. if (Size < sizeof(NETBT_ADD_DEL_IF))
  547. {
  548. KdPrint(("Nbt.NbtAddNewInterface: Output buffer too small for struct\n"));
  549. NbtTrace(NBT_TRACE_PNP, ("Output buffer too small for struct size=%d, required=%d",
  550. Size, sizeof(NETBT_ADD_DEL_IF)));
  551. return(STATUS_INVALID_PARAMETER);
  552. }
  553. //
  554. // Create the bind/export strings as:
  555. // Bind: \Device\IF<1> Export: \Device\NetBt_IF<1>
  556. // where 1 is a unique interface index.
  557. //
  558. ucSuffix.Buffer = Suffix;
  559. ucSuffix.Length = 0;
  560. ucSuffix.MaximumLength = sizeof(Suffix);
  561. RtlIntegerToUnicodeString(nextIndex, 10, &ucSuffix);
  562. RtlInitUnicodeString(&ucBindStr, Bind);
  563. ucBindStr.MaximumLength = sizeof(Bind);
  564. RtlInitUnicodeString(&ucExportStr, Export);
  565. ucExportStr.MaximumLength = sizeof(Export);
  566. RtlAppendUnicodeStringToString(&ucBindStr, &ucSuffix);
  567. RtlAppendUnicodeStringToString(&ucExportStr, &ucSuffix);
  568. OutSize = FIELD_OFFSET (NETBT_ADD_DEL_IF, IfName[0]) +
  569. ucExportStr.Length + sizeof(UNICODE_NULL);
  570. if (Size < OutSize)
  571. {
  572. KdPrint(("Nbt.NbtAddNewInterface: Buffer too small for name\n"));
  573. NbtTrace(NBT_TRACE_PNP, ("Buffer too small for name size=%d, required=%d", Size, OutSize));
  574. pAddDelIf->Length = ucExportStr.Length + sizeof(UNICODE_NULL);
  575. pAddDelIf->Status = STATUS_BUFFER_TOO_SMALL;
  576. pIrp->IoStatus.Information = sizeof(NETBT_ADD_DEL_IF);
  577. return STATUS_SUCCESS;
  578. }
  579. IF_DBG(NBT_DEBUG_PNP_POWER)
  580. KdPrint(( "Nbt.NbtAddNewInterface: Creating ucBindStr: %ws ucExportStr: %ws\n",
  581. ucBindStr.Buffer, ucExportStr.Buffer ));
  582. //
  583. // Attach to the system process so that all handles are created in the
  584. // proper context.
  585. //
  586. CTEAttachFsp(&Attached, REF_FSP_ADD_INTERFACE);
  587. status = NbtCreateDeviceObject (&ucBindStr,
  588. &ucExportStr,
  589. &pAddrArray[0],
  590. &pDeviceContext,
  591. NBT_DEVICE_CLUSTER);
  592. CTEDetachFsp(Attached, REF_FSP_ADD_INTERFACE);
  593. if (pDeviceContext)
  594. {
  595. //
  596. // Fill up the output buffer with the export name
  597. //
  598. RtlCopyMemory(&pAddDelIf->IfName[0], ucExportStr.Buffer, ucExportStr.Length+sizeof(UNICODE_NULL));
  599. pAddDelIf->Length = ucExportStr.Length + sizeof(UNICODE_NULL);
  600. pAddDelIf->InstanceNumber = pDeviceContext->InstanceNumber;
  601. pAddDelIf->Status = STATUS_SUCCESS;
  602. pIrp->IoStatus.Information = OutSize;
  603. //
  604. // By-pass the TDI PnP mechanism for logical interfaces (ie don't register with TDI)
  605. //
  606. return (STATUS_SUCCESS);
  607. }
  608. NbtTrace(NBT_TRACE_PNP, ("NbtCreateDeviceObject return %!status! for BindName=%Z ExportName=%Z",
  609. status, &ucBindStr, &ucExportStr));
  610. return status;
  611. }
  612. NTSTATUS
  613. NbtDeviceAdd(
  614. PUNICODE_STRING pucBindString
  615. )
  616. {
  617. tDEVICECONTEXT *pDeviceContext;
  618. UNICODE_STRING ucExportString;
  619. tADDRARRAY DeviceAddressArray;
  620. BOOLEAN Attached = FALSE;
  621. NTSTATUS Status;
  622. PLIST_ENTRY pHead, pEntry;
  623. NTSTATUS dontcarestatus;
  624. int i;
  625. CTEPagedCode();
  626. //
  627. // Ignore it if we already bind to the device
  628. //
  629. if (pDeviceContext = NbtFindAndReferenceDevice (pucBindString, TRUE)) {
  630. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, FALSE);
  631. KdPrint (("Nbt.NbtDeviceAdd: ERROR: Device=<%ws> already exists!\n", pucBindString->Buffer));
  632. NbtTrace(NBT_TRACE_PNP, ("Device %Z already exists!", pucBindString));
  633. return STATUS_SUCCESS;
  634. }
  635. //
  636. // Can we find the new device in registry file? If not, ignore it.
  637. //
  638. Status = LookupDeviceInRegistry(pucBindString, &DeviceAddressArray, &ucExportString);
  639. if (!NT_SUCCESS(Status)) {
  640. KdPrint(("netbt!NbtDeviceAdd: Cannot find device in the registry: status <%x>\n", Status));
  641. NbtTrace(NBT_TRACE_PNP, ("LookupDeviceInRegistry return %!status! for device %Z",
  642. Status, pucBindString));
  643. return STATUS_UNSUCCESSFUL;
  644. }
  645. //
  646. // Attach to the system process so that all handles are created in the
  647. // proper context.
  648. //
  649. CTEAttachFsp(&Attached, REF_FSP_DEVICE_ADD);
  650. Status = NbtCreateDeviceObject (pucBindString,
  651. &ucExportString,
  652. &DeviceAddressArray,
  653. &pDeviceContext,
  654. NBT_DEVICE_REGULAR);
  655. CTEMemFree(ucExportString.Buffer);
  656. CTEDetachFsp(Attached, REF_FSP_DEVICE_ADD);
  657. //
  658. // Call Tdi to re-enumerate the addresses for us
  659. //
  660. if (NT_SUCCESS (Status)) {
  661. TdiEnumerateAddresses(TdiClientHandle);
  662. } else {
  663. KdPrint (("Nbt.NbtDeviceAdd: ERROR: NbtCreateDeviceObject returned <%x>\n", Status));
  664. NbtTrace(NBT_TRACE_PNP, ("NbtCreateDeviceObject return %!status! for device %Z",
  665. Status, pucBindString));
  666. }
  667. return (Status);
  668. }
  669. // TdiAddressArrival - PnP TDI_ADD_ADDRESS_HANDLER
  670. // Handles an IP address arriving
  671. // Called by TDI when an address arrives.
  672. //
  673. // Input: Addr - IP address that's coming.
  674. //
  675. // Returns: Nothing.
  676. //
  677. VOID
  678. TdiAddressArrival(
  679. PTA_ADDRESS Addr,
  680. PUNICODE_STRING pDeviceName,
  681. PTDI_PNP_CONTEXT Context
  682. )
  683. {
  684. ULONG IpAddr, LastAssignedIpAddress;
  685. tDEVICECONTEXT *pDeviceContext;
  686. PTDI_PNP_CONTEXT pTdiContext;
  687. NTSTATUS status;
  688. CTEPagedCode();
  689. pDeviceContext = CheckAddrNotification(Addr, pDeviceName, &IpAddr);
  690. if (pDeviceContext == NULL) {
  691. return;
  692. }
  693. //
  694. // Now the device is referenced!!!
  695. //
  696. NbtTrace(NBT_TRACE_PNP, ("TdiAddressArrival for %Z, IpAddr=%!ipaddr!, "
  697. "pDeviceContext->AssignedIpAddress=%!ipaddr!, pDeviceContext->IpAddress=%!ipaddr!",
  698. pDeviceName, IpAddr, pDeviceContext->AssignedIpAddress, pDeviceContext->IpAddress));
  699. //
  700. // Update the PDO in Context2
  701. //
  702. pTdiContext = (PTDI_PNP_CONTEXT) &pDeviceContext->Context2;
  703. pTdiContext->ContextSize = Context->ContextSize;
  704. pTdiContext->ContextType = Context->ContextType;
  705. *(PVOID UNALIGNED*) pTdiContext->ContextData = *(PVOID UNALIGNED*) Context->ContextData;
  706. LastAssignedIpAddress = pDeviceContext->AssignedIpAddress;
  707. if (NT_SUCCESS (status = NbtAddressAdd(IpAddr, pDeviceContext, pDeviceName))) {
  708. // Register Smb Device
  709. // Assumption 1: tdi can assign multiple addresses to same device
  710. // Assumption 2: tdi will always delete an assignment it made
  711. // THIS IS CODED FOR ONE ADDRESS PER DEVICE
  712. // First assigned address wins (and is reference counted)
  713. if (LastAssignedIpAddress == 0) {
  714. if ((1 == InterlockedIncrement (&AddressCount)) && (NbtConfig.SMBDeviceEnabled)) {
  715. IF_DBG(NBT_DEBUG_PNP_POWER)
  716. KdPrint(("Nbt.TdiAddressArrival: Registering NetbiosSmb Device\n"));
  717. SmbNotifyTdiClients (NBT_TDI_REGISTER);
  718. }
  719. }
  720. } else {
  721. NbtTrace(NBT_TRACE_PNP, ("NbtAddressAdd return %!status! for device %Z",
  722. status, pDeviceName));
  723. }
  724. //
  725. // Derefenece the device
  726. //
  727. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, FALSE);
  728. SetNodeType();
  729. }
  730. // TdiAddressDeletion - PnP TDI_DEL_ADDRESS_HANDLER
  731. // Handles an IP address going away.
  732. // Called by TDI when an address is deleted. If it's an address we
  733. // care about we'll clean up appropriately.
  734. //
  735. // Input: Addr - IP address that's going.
  736. //
  737. // Returns: Nothing.
  738. //
  739. VOID
  740. TdiAddressDeletion(
  741. PTA_ADDRESS Addr,
  742. PUNICODE_STRING pDeviceName,
  743. PTDI_PNP_CONTEXT Context
  744. )
  745. {
  746. ULONG IpAddr;
  747. tDEVICECONTEXT *pDeviceContext;
  748. CTEPagedCode();
  749. pDeviceContext = CheckAddrNotification(Addr, pDeviceName, &IpAddr);
  750. if (pDeviceContext == NULL) {
  751. return;
  752. }
  753. //
  754. // Now the device is referenced!!!
  755. //
  756. NbtTrace(NBT_TRACE_PNP, ("TdiAddressDeletion for %Z, IpAddr=%!ipaddr!, "
  757. "pDeviceContext->AssignedIpAddress=%!ipaddr!, pDeviceContext->IpAddress=%!ipaddr!",
  758. pDeviceName, IpAddr, pDeviceContext->AssignedIpAddress, pDeviceContext->IpAddress));
  759. // Deregister Smb Device
  760. // THIS IS CODED FOR ONE ADDRESS PER DEVICE
  761. // Only deletion of an assigned address wins (and is ref counted)
  762. if (pDeviceContext->AssignedIpAddress == IpAddr) {
  763. if ((0 == InterlockedDecrement (&AddressCount))) {
  764. IF_DBG(NBT_DEBUG_PNP_POWER)
  765. KdPrint(("Nbt.TdiAddressDeletion: Deregistering NetbiosSmb Device\n"));
  766. SmbNotifyTdiClients (NBT_TDI_DEREGISTER);
  767. }
  768. pDeviceContext->AssignedIpAddress = 0;
  769. if (IpAddr == pDeviceContext->IpAddress) {
  770. NbtNewDhcpAddress(pDeviceContext, 0, 0);
  771. }
  772. }
  773. //
  774. // Derefenece the device
  775. //
  776. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, FALSE);
  777. SetNodeType();
  778. }
  779. VOID
  780. TdiBindHandler(
  781. TDI_PNP_OPCODE PnPOpCode,
  782. PUNICODE_STRING pDeviceName,
  783. PWSTR MultiSZBindList)
  784. {
  785. NTSTATUS Status;
  786. tDEVICECONTEXT *pDeviceContext;
  787. CTEPagedCode();
  788. switch (PnPOpCode)
  789. {
  790. case (TDI_PNP_OP_ADD):
  791. {
  792. //
  793. // Ignore TCPIP6 interface
  794. //
  795. if (IsIPv6Interface(pDeviceName)) {
  796. return;
  797. }
  798. Status = NbtDeviceAdd (pDeviceName);
  799. if (!NT_SUCCESS(Status))
  800. {
  801. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_ADD]: ERROR <%x>, AdapterCount=<%x>\n",
  802. Status, NbtConfig.AdapterCount));
  803. NbtLogEvent (EVENT_NBT_CREATE_DEVICE, Status, 0x111);
  804. }
  805. NbtTrace(NBT_TRACE_PNP, ("NbtDeviceAdd return %!status! for %Z", Status, pDeviceName));
  806. break;
  807. }
  808. case (TDI_PNP_OP_DEL):
  809. {
  810. //
  811. // If the Device is Valid, Dereference it!
  812. //
  813. if (pDeviceContext = NbtFindAndReferenceDevice (pDeviceName, TRUE))
  814. {
  815. IF_DBG(NBT_DEBUG_PNP_POWER)
  816. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_DEL]: Dereferencing Device <%wZ>\n",
  817. &pDeviceContext->BindName));
  818. // Deref it since we referenced it above!
  819. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, FALSE);
  820. Status = NbtDestroyDevice (pDeviceContext, TRUE);
  821. NbtTrace(NBT_TRACE_PNP, ("NbtDestoryDevice return %!status! for %Z", Status, pDeviceName));
  822. }
  823. else
  824. {
  825. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_DEL]: ERROR -- Device=<%wZ>\n", pDeviceName));
  826. NbtTrace(NBT_TRACE_PNP, ("NbtFindAndReferenceDevice return NULL for %Z", pDeviceName));
  827. }
  828. break;
  829. }
  830. case (TDI_PNP_OP_UPDATE):
  831. {
  832. tDEVICES *pBindDevices = NULL;
  833. tDEVICES *pExportDevices = NULL;
  834. tADDRARRAY *pAddrArray = NULL;
  835. IF_DBG(NBT_DEBUG_PNP_POWER)
  836. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_UPDATE]: Got Update Notification\n"));
  837. //
  838. // Re-read the registry
  839. //
  840. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  841. NbtReadRegistry (&pBindDevices, &pExportDevices, &pAddrArray);
  842. NbtReadRegistryCleanup (&pBindDevices, &pExportDevices, &pAddrArray);
  843. CTEExReleaseResource(&NbtConfig.Resource);
  844. SetNodeType();
  845. NbtTrace(NBT_TRACE_PNP, ("[TDI_PNP_OP_UPDATE]"));
  846. break;
  847. }
  848. case (TDI_PNP_OP_PROVIDERREADY):
  849. {
  850. WCHAR wcIpDeviceName[60] = DD_IP_DEVICE_NAME;
  851. UNICODE_STRING ucIpDeviceName;
  852. RtlInitUnicodeString(&ucIpDeviceName, wcIpDeviceName);
  853. ucIpDeviceName.MaximumLength = sizeof (wcIpDeviceName);
  854. IF_DBG(NBT_DEBUG_PNP_POWER)
  855. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_NETREADY]: Comparing <%wZ> with <%wZ>\n",
  856. pDeviceName, &ucIpDeviceName));
  857. NbtTrace(NBT_TRACE_PNP, ("[TDI_PNP_OP_NETREADY]: <%Z> <==> <%Z>", pDeviceName, &ucIpDeviceName));
  858. //
  859. // Use case-insensitive compare since registry is case-insensitive
  860. //
  861. if (RtlCompareUnicodeString(pDeviceName, &ucIpDeviceName, TRUE) == 0)
  862. {
  863. //
  864. // This is the notification we were waiting for from Ip, so now
  865. // notify our clients of our completion status as a provider!
  866. //
  867. IF_DBG(NBT_DEBUG_PNP_POWER)
  868. KdPrint(("Nbt.TdiBindHandler[TDI_PNP_OP_NETREADY]: Got Ip Notification\n"));
  869. //#if DBG
  870. TcpipReady = TRUE;
  871. //#endif
  872. NbtDownBootCounter();
  873. }
  874. break;
  875. }
  876. case (TDI_PNP_OP_NETREADY):
  877. {
  878. // Nothing to do!
  879. NbtTrace(NBT_TRACE_PNP, ("[TDI_PNP_OP_NETREADY]"));
  880. break;
  881. }
  882. default:
  883. {
  884. KdPrint(("Nbt.TdiBindHandler: Unknown Opcode=<%x>\n", PnPOpCode));
  885. NbtTrace(NBT_TRACE_PNP, ("Unknown Opcode=<%x>", PnPOpCode));
  886. ASSERT (0);
  887. }
  888. }
  889. }
  890. tDEVICECONTEXT *
  891. NbtCreateSmbDevice(
  892. )
  893. /*++
  894. Routine Description:
  895. The model of this device is different from the rest of the Netbt devices in that netbt devices
  896. are per-adapter. For this device there is only one instance across all adapters.
  897. This is the code that creates the Smb device. We create it at DriverEntry and Destory it
  898. at driver Unload time.
  899. We try to call existing routines to create the new device, so that we can reuse as much code
  900. as possible and have the new device initialized identically to the other netbt devices. Then
  901. we customize this device by setting some variables controlling port and endpoint.
  902. In the current design, a message-only Netbt device is only single session. Different sessions,
  903. or applications, use different Tcp ports. Each message-only Netbt device is assigned a single
  904. port, such as Smb. If you want to
  905. support a different application over Netbt, The easiest thing is to instantiate a new message-only
  906. device with a different Tcp port. Perhaps there is a way to delay the binding of the port on the
  907. client side from device creation to connection creation?
  908. Another idea to consider is to modularize the construction of these message-only devices. You
  909. could have a table in the registry naming the device, with its unique initialization parameters.
  910. This code could then read the table.
  911. Create and initialize the message special device.
  912. This function is not driven by Pnp because it is not adapter specific.
  913. The idea here was to abstract the details of special devices as much as possible. The way
  914. the current code is written, you must have a single port for each device. This means you
  915. typically will get one application for each special device. Right now the only case is
  916. rdr/srv using message-mode for smb traffic. In the future, if you had another netbios session
  917. application that wanted an internet pure device, you could just call this routine with the
  918. new parameters.
  919. Two issues that I can think of:
  920. 1. The default session name is still hardcoded. You might want to pass that in here if you
  921. didn't want *smbserver as the session name.
  922. 2. Binding is per application. Currently there is a .Inf file to get Smb bound to the rdr
  923. and srv. If you have a new application and a new special device, you will need another .inf
  924. file.
  925. Arguments:
  926. Return Value:
  927. NTSTATUS -
  928. --*/
  929. {
  930. NTSTATUS Status;
  931. BOOLEAN Attached = FALSE;
  932. tDEVICECONTEXT *pDeviceContext = NULL;
  933. NBT_WORK_ITEM_CONTEXT *pContext;
  934. UNICODE_STRING ucSmbDeviceBindName;
  935. UNICODE_STRING ucSmbDeviceExportName;
  936. WCHAR Path[MAX_PATH];
  937. UNICODE_STRING ParamPath;
  938. OBJECT_ATTRIBUTES TmpObjectAttributes;
  939. HANDLE Handle;
  940. ULONG Metric;
  941. CTEPagedCode();
  942. NbtTrace(NBT_TRACE_PNP, ("Creating Smb device"));
  943. RtlInitUnicodeString(&ucSmbDeviceBindName, WC_SMB_DEVICE_BIND_NAME);
  944. ucSmbDeviceBindName.MaximumLength = sizeof (WC_SMB_DEVICE_BIND_NAME);
  945. RtlInitUnicodeString(&ucSmbDeviceExportName, WC_SMB_DEVICE_EXPORT_NAME);
  946. ucSmbDeviceExportName.MaximumLength = sizeof (WC_SMB_DEVICE_EXPORT_NAME);
  947. CTEAttachFsp(&Attached, REF_FSP_CREATE_SMB_DEVICE);
  948. //
  949. // Create the SMBDevice
  950. //
  951. Status = NbtCreateDeviceObject (&ucSmbDeviceBindName, // Bind name, ignored, but must match for delete
  952. &ucSmbDeviceExportName, // Export name
  953. NULL,
  954. &pDeviceContext,
  955. NBT_DEVICE_NETBIOSLESS);// message-only Netbt device
  956. if (NT_SUCCESS(Status))
  957. {
  958. pDeviceContext->SessionPort = NbtConfig.DefaultSmbSessionPort;
  959. pDeviceContext->DatagramPort = NbtConfig.DefaultSmbDatagramPort;
  960. pDeviceContext->NameServerPort = 0; // Disable this port for security reasons
  961. RtlCopyMemory (pDeviceContext->MessageEndpoint, "*SMBSERVER ", NETBIOS_NAME_SIZE );
  962. //
  963. // Here is where we initialize the handles in the special device
  964. // Create the handles to the transport. This does not depend on dhcp
  965. // Use LOOP_BACK because we need to put something non-zero here
  966. //
  967. // This device is registered based on address notifications
  968. //
  969. // Status = NbtCreateAddressObjects (LOOP_BACK, 0, pDeviceContext);
  970. Status = NbtCreateAddressObjects (INADDR_LOOPBACK, 0, pDeviceContext);
  971. pDeviceContext->BroadcastAddress = LOOP_BACK; // Make sure no broadcasts
  972. if (NT_SUCCESS(Status))
  973. {
  974. //
  975. // Now clear the If lists and add the INADDR_LOOPBACK address
  976. //
  977. if (pDeviceContext->hSession)
  978. {
  979. NbtSetTcpInfo (pDeviceContext->hSession,
  980. AO_OPTION_IFLIST,
  981. INFO_TYPE_ADDRESS_OBJECT,
  982. (ULONG) TRUE);
  983. NbtSetTcpInfo (pDeviceContext->hSession,
  984. AO_OPTION_ADD_IFLIST,
  985. INFO_TYPE_ADDRESS_OBJECT,
  986. pDeviceContext->IPInterfaceContext);
  987. }
  988. //
  989. // Now, set the same for the Datagram port
  990. //
  991. if ((pDeviceContext->pFileObjects) &&
  992. (pDeviceContext->pFileObjects->hDgram))
  993. {
  994. NbtSetTcpInfo (pDeviceContext->pFileObjects->hDgram,
  995. AO_OPTION_IFLIST,
  996. INFO_TYPE_ADDRESS_OBJECT,
  997. (ULONG) TRUE);
  998. NbtSetTcpInfo (pDeviceContext->pFileObjects->hDgram,
  999. AO_OPTION_ADD_IFLIST,
  1000. INFO_TYPE_ADDRESS_OBJECT,
  1001. pDeviceContext->IPInterfaceContext);
  1002. }
  1003. NbtTrace(NBT_TRACE_PNP, ("Successful creating Smb device"));
  1004. }
  1005. else
  1006. {
  1007. KdPrint (("Nbt.NbtCreateSmbDevice: NbtCreateAddressObjects Failed, status = <%x>\n", Status));
  1008. NbtTrace(NBT_TRACE_PNP, ("NbtCreateAddressObject Failed with %!status!", Status));
  1009. }
  1010. }
  1011. else
  1012. {
  1013. KdPrint (("Nbt.NbtCreateSmbDevice: NbtCreateDeviceObject Failed, status = <%x>\n", Status));
  1014. NbtTrace(NBT_TRACE_PNP, ("NbtCreateDeviceObject Failed with %!status!", Status));
  1015. }
  1016. CTEDetachFsp(Attached, REF_FSP_CREATE_SMB_DEVICE);
  1017. return (pDeviceContext);
  1018. }
  1019. VOID
  1020. NbtPnPPowerComplete(
  1021. IN PNET_PNP_EVENT NetEvent,
  1022. IN NTSTATUS ProviderStatus
  1023. )
  1024. {
  1025. CTEPagedCode();
  1026. TdiPnPPowerComplete (TdiClientHandle, NetEvent, ProviderStatus);
  1027. NbtTrace(NBT_TRACE_PNP, ("[NbtPnPPowerComplete]"));
  1028. }
  1029. NTSTATUS
  1030. TdiPnPPowerHandler(
  1031. IN PUNICODE_STRING pDeviceName,
  1032. IN PNET_PNP_EVENT PnPEvent,
  1033. IN PTDI_PNP_CONTEXT Context1,
  1034. IN PTDI_PNP_CONTEXT Context2
  1035. )
  1036. {
  1037. tDEVICECONTEXT *pDeviceContext = NULL;
  1038. NTSTATUS status = STATUS_SUCCESS; // Success by default!
  1039. PNETBT_PNP_RECONFIG_REQUEST PnPEventBuffer = (PNETBT_PNP_RECONFIG_REQUEST) PnPEvent->Buffer;
  1040. PNET_DEVICE_POWER_STATE pPowerState = (PNET_DEVICE_POWER_STATE) PnPEventBuffer; // Power requests
  1041. BOOLEAN fWait = FALSE;
  1042. #ifdef _NETBIOSLESS
  1043. BOOLEAN fOldNetbiosEnabledState;
  1044. #endif
  1045. CTEPagedCode();
  1046. //
  1047. // Pass the request up first
  1048. //
  1049. if ((pDeviceName) && (pDeviceName->Length)) {
  1050. if (!(pDeviceContext = NbtFindAndReferenceDevice (pDeviceName, TRUE))) {
  1051. return (STATUS_SUCCESS);
  1052. }
  1053. #ifdef _NETBIOSLESS
  1054. fOldNetbiosEnabledState = pDeviceContext->NetbiosEnabled;
  1055. #endif
  1056. } else if (PnPEvent->NetEvent != NetEventReconfigure) {
  1057. //
  1058. // pDeviceName is not set for Reconfigure events
  1059. // The only valid case for no Device to be specified is Reconfigure!
  1060. //
  1061. return STATUS_UNSUCCESSFUL;
  1062. }
  1063. IF_DBG(NBT_DEBUG_PNP_POWER)
  1064. KdPrint(("Nbt.NbtTdiPnpPowerHandler: Device=<%wZ>, Event=<%d>, C1=<%p>, C2=<%p>\n",
  1065. pDeviceName, PnPEvent->NetEvent, Context1, Context2 ));
  1066. NbtTrace(NBT_TRACE_PNP, ("Device=<%Z>, Event=<%d>, C1=<%p>, C2=<%p>",
  1067. pDeviceName, PnPEvent->NetEvent, Context1, Context2));
  1068. switch (PnPEvent->NetEvent)
  1069. {
  1070. case (NetEventQueryPower):
  1071. {
  1072. //
  1073. // Check if we should veto this request
  1074. //
  1075. if ((*pPowerState != NetDeviceStateD0) &&
  1076. (NbtConfig.MinimumRefreshSleepTimeout == 0))
  1077. {
  1078. status = STATUS_UNSUCCESSFUL;
  1079. break;
  1080. }
  1081. status = TdiPnPPowerRequest (&pDeviceContext->ExportName, PnPEvent, Context1, Context2, NbtPnPPowerComplete);
  1082. IF_DBG(NBT_DEBUG_PNP_POWER)
  1083. KdPrint(("Nbt.TdiPnPPowerHandler[QueryPower]: Device=<%x>, PowerState=<%x>, status=<%x>\n",
  1084. pDeviceContext, *pPowerState, status));
  1085. NbtTrace(NBT_TRACE_PNP, ("[QueryPower]: Device=<%Z>, PowerState=<%x>, status=%!status!",
  1086. pDeviceName, *pPowerState, status));
  1087. //
  1088. // NetBt doesn't need to do anything here, so we'll just return!
  1089. //
  1090. break;
  1091. }
  1092. case (NetEventSetPower):
  1093. {
  1094. //
  1095. // Check if we should veto this request (if requested by user)
  1096. //
  1097. if ((*pPowerState != NetDeviceStateD0) &&
  1098. (NbtConfig.MinimumRefreshSleepTimeout == 0))
  1099. {
  1100. status = STATUS_UNSUCCESSFUL;
  1101. break;
  1102. }
  1103. status = TdiPnPPowerRequest (&pDeviceContext->ExportName, PnPEvent, Context1, Context2, NbtPnPPowerComplete);
  1104. IF_DBG(NBT_DEBUG_PNP_POWER)
  1105. KdPrint(("Nbt.TdiPnPPowerHandler[SetPower]: Device=<%x>, PowerState=<%d=>%d>, status=<%x>\n",
  1106. pDeviceContext, LastSystemPowerState, *pPowerState, status));
  1107. NbtTrace(NBT_TRACE_PNP, ("[SetPower]: Device=<%Z>, PowerState=<%x>, status=%!status!",
  1108. pDeviceName, *pPowerState, status));
  1109. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  1110. if (*pPowerState != LastSystemPowerState) // this is a state transition
  1111. {
  1112. switch (*pPowerState)
  1113. {
  1114. case NetDeviceStateD0:
  1115. {
  1116. NbtConfig.GlobalRefreshState &= ~NBT_G_REFRESH_SLEEPING;
  1117. if (NbtConfig.pWakeupRefreshTimer)
  1118. {
  1119. if (NT_SUCCESS (NTQueueToWorkerThread(NULL, DelayedNbtStopWakeupTimer,
  1120. NULL,
  1121. NbtConfig.pWakeupRefreshTimer,
  1122. NULL, NULL, FALSE)))
  1123. {
  1124. NbtConfig.pWakeupRefreshTimer->RefCount++;
  1125. NbtConfig.pWakeupRefreshTimer = NULL;
  1126. }
  1127. // Ignore the return status! (Best effort!)
  1128. StartTimer(RefreshTimeout,
  1129. NbtConfig.InitialRefreshTimeout/NbtConfig.RefreshDivisor,
  1130. NULL, // context value
  1131. NULL, // context2 value
  1132. NULL,
  1133. NULL,
  1134. NULL, // This Timer is Global!
  1135. &NbtConfig.pRefreshTimer,
  1136. 0,
  1137. FALSE);
  1138. }
  1139. break;
  1140. }
  1141. case NetDeviceStateD1:
  1142. case NetDeviceStateD2:
  1143. case NetDeviceStateD3:
  1144. {
  1145. if (LastSystemPowerState != NetDeviceStateD0) // Don't differentiate bw D1, D2, & D3
  1146. {
  1147. break;
  1148. }
  1149. //
  1150. // Reset the Refresh Timer to function accordingly
  1151. //
  1152. NbtStopRefreshTimer();
  1153. ASSERT (!NbtConfig.pWakeupRefreshTimer);
  1154. NbtConfig.GlobalRefreshState |= NBT_G_REFRESH_SLEEPING;
  1155. KeClearEvent (&NbtConfig.WakeupTimerStartedEvent);
  1156. if (NT_SUCCESS (NTQueueToWorkerThread(NULL, DelayedNbtStartWakeupTimer,
  1157. NULL,
  1158. NULL,
  1159. NULL,
  1160. NULL,
  1161. FALSE)))
  1162. {
  1163. fWait = TRUE;
  1164. }
  1165. break;
  1166. }
  1167. default:
  1168. {
  1169. ASSERT (0);
  1170. }
  1171. }
  1172. LastSystemPowerState = *pPowerState;
  1173. }
  1174. CTEExReleaseResource(&NbtConfig.Resource);
  1175. if (fWait)
  1176. {
  1177. NTSTATUS status;
  1178. status = KeWaitForSingleObject (&NbtConfig.WakeupTimerStartedEvent, // Object to wait on.
  1179. Executive, // Reason for waiting
  1180. KernelMode, // Processor mode
  1181. FALSE, // Alertable
  1182. NULL); // Timeout
  1183. ASSERT(status == STATUS_SUCCESS);
  1184. }
  1185. break;
  1186. }
  1187. case (NetEventQueryRemoveDevice):
  1188. {
  1189. status = TdiPnPPowerRequest (&pDeviceContext->ExportName, PnPEvent, Context1, Context2, NbtPnPPowerComplete);
  1190. IF_DBG(NBT_DEBUG_PNP_POWER)
  1191. KdPrint(("Nbt.TdiPnPPowerHandler: NetEventQueryRemoveDevice -- status=<%x>\n",status));
  1192. NbtTrace(NBT_TRACE_PNP, ("[NetEventQueryRemoveDevice]: Device=<%Z>, status=%!status!",
  1193. pDeviceName, status));
  1194. break;
  1195. }
  1196. case (NetEventCancelRemoveDevice):
  1197. {
  1198. status = TdiPnPPowerRequest (&pDeviceContext->ExportName, PnPEvent, Context1, Context2, NbtPnPPowerComplete);
  1199. IF_DBG(NBT_DEBUG_PNP_POWER)
  1200. KdPrint(("Nbt.TdiPnPPowerHandler: NetEventCancelRemoveDevice -- status=<%x>\n",status));
  1201. NbtTrace(NBT_TRACE_PNP, ("[NetEventCancelRemoveDevice]: Device=<%Z>, status=%!status!",
  1202. pDeviceName, status));
  1203. break;
  1204. }
  1205. case (NetEventReconfigure):
  1206. {
  1207. //
  1208. // First check if the WINs server entries have been modified
  1209. //
  1210. if (pDeviceContext)
  1211. {
  1212. IF_DBG(NBT_DEBUG_PNP_POWER)
  1213. KdPrint (("Nbt.TdiPnPPowerHandler: WINs servers have changed for <%x>\n",pDeviceContext));
  1214. status = NTReReadRegistry (pDeviceContext, TRUE);
  1215. NbtTrace(NBT_TRACE_PNP, ("[NetEventReconfigure]: WINs servers have changed for %Z, status=%!status!",
  1216. pDeviceName, status));
  1217. }
  1218. else // check the rest of the options
  1219. {
  1220. #if 0
  1221. // EnumDnsOption is no longer set through the UI, so we can ignore this!
  1222. IF_DBG(NBT_DEBUG_PNP_POWER)
  1223. KdPrint (("Nbt.TdiPnPPowerHandler: Checking EnumDNS option for <%x>\n",pDeviceContext));
  1224. switch (PnPEventBuffer->enumDnsOption)
  1225. {
  1226. case (WinsOnly):
  1227. NbtConfig.UseDnsOnly = FALSE;
  1228. NbtConfig.ResolveWithDns = FALSE;
  1229. break;
  1230. case (DnsOnly):
  1231. NbtConfig.UseDnsOnly = TRUE;
  1232. NbtConfig.ResolveWithDns = TRUE;
  1233. break;
  1234. case (WinsThenDns):
  1235. NbtConfig.UseDnsOnly = FALSE;
  1236. NbtConfig.ResolveWithDns = TRUE;
  1237. break;
  1238. default:
  1239. KdPrint (("Nbt.TdiPnPPowerHandler: ERROR bad option for enumDnsOption <%x>\n",
  1240. PnPEventBuffer->enumDnsOption));
  1241. }
  1242. #endif // 0
  1243. if (PnPEventBuffer->fLmhostsEnabled)
  1244. {
  1245. if ((!NbtConfig.EnableLmHosts) || // if the user is re-enabling LmHosts
  1246. (PnPEventBuffer->fLmhostsFileSet)) // the user wants to use a new LmHosts file
  1247. {
  1248. tDEVICES *pBindDevices=NULL;
  1249. tDEVICES *pExportDevices=NULL;
  1250. tADDRARRAY *pAddrArray=NULL;
  1251. IF_DBG(NBT_DEBUG_PNP_POWER)
  1252. KdPrint (("Nbt.TdiPnPPowerHandler: Reading LmHosts file\n"));
  1253. //
  1254. // ReRead the registry for the LmHost options
  1255. //
  1256. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  1257. status = NbtReadRegistry (&pBindDevices, &pExportDevices, &pAddrArray);
  1258. NbtReadRegistryCleanup(&pBindDevices, &pExportDevices, &pAddrArray);
  1259. CTEExReleaseResource(&NbtConfig.Resource);
  1260. DelayedNbtResyncRemoteCache(NULL, NULL, NULL, NULL);
  1261. }
  1262. }
  1263. else
  1264. {
  1265. NbtConfig.EnableLmHosts = PnPEventBuffer->fLmhostsEnabled;
  1266. }
  1267. }
  1268. IF_DBG(NBT_DEBUG_PNP_POWER)
  1269. KdPrint(("Nbt.TdiPnPPowerHandler: NetEventReconfigure -- status=<%x>\n",status));
  1270. NbtTrace(NBT_TRACE_PNP, ("NetEventReconfigure -- %Z status=%!status!", pDeviceName, status));
  1271. break;
  1272. }
  1273. case (NetEventBindList):
  1274. {
  1275. //
  1276. // Just do a general reread of the registry parameters since we could
  1277. // get WINS address change notifications through here!
  1278. //
  1279. if (pDeviceContext)
  1280. {
  1281. IF_DBG(NBT_DEBUG_PNP_POWER)
  1282. KdPrint (("Nbt.TdiPnPPowerHandler: NetEventBindList request for <%x>\n",pDeviceContext));
  1283. status = NTReReadRegistry (pDeviceContext, TRUE);
  1284. }
  1285. IF_DBG(NBT_DEBUG_PNP_POWER)
  1286. KdPrint(("Nbt.TdiPnPPowerHandler: NetEventBindList -- status=<%x>\n",status));
  1287. break;
  1288. }
  1289. case (NetEventPnPCapabilities):
  1290. {
  1291. //
  1292. // Query into TcpIp to get the latest Pnp properties on this device!
  1293. //
  1294. if (pDeviceContext)
  1295. {
  1296. PULONG pResult = NULL;
  1297. ULONG BufferLen = sizeof (ULONG);
  1298. ULONG Input = pDeviceContext->IPInterfaceContext;
  1299. //
  1300. // Query the latest WOL capabilities on this adapter!
  1301. //
  1302. if (NT_SUCCESS (status = NbtProcessIPRequest (IOCTL_IP_GET_WOL_CAPABILITY,
  1303. &Input, // Input buffer
  1304. BufferLen,
  1305. (PVOID) &pResult,
  1306. &BufferLen)))
  1307. {
  1308. ASSERT (pResult);
  1309. pDeviceContext->WOLProperties = *pResult;
  1310. CTEMemFree (pResult);
  1311. }
  1312. IF_DBG(NBT_DEBUG_PNP_POWER)
  1313. KdPrint (("Nbt.TdiPnPPowerHandler[NetEventPnPCapabilities] <%x>, pDeviceContext=<%p>, Input=<%x>, Result=<%x>\n",status, pDeviceContext, Input, pDeviceContext->WOLProperties));
  1314. status = STATUS_SUCCESS;
  1315. }
  1316. break;
  1317. }
  1318. default:
  1319. KdPrint(("Nbt.TdiPnPPowerHandler: Invalid NetEvent=<%x> -- status=<%x>\n",
  1320. PnPEvent->NetEvent,status));
  1321. }
  1322. if (pDeviceContext) {
  1323. #ifdef _NETBIOSLESS
  1324. //
  1325. // Check for transition in Netbios enable state
  1326. //
  1327. if (fOldNetbiosEnabledState != pDeviceContext->NetbiosEnabled)
  1328. {
  1329. if (pDeviceContext->NetbiosEnabled)
  1330. {
  1331. IF_DBG(NBT_DEBUG_PNP_POWER)
  1332. KdPrint(("Nbt.NbtTdiPnpPowerHandler: Enabling address on %wZ\n",
  1333. &pDeviceContext->ExportName));
  1334. // We don't know what the right IP address is,
  1335. // so we tell TDI to Enumerate!
  1336. TdiEnumerateAddresses(TdiClientHandle);
  1337. }
  1338. else
  1339. {
  1340. IF_DBG(NBT_DEBUG_PNP_POWER)
  1341. KdPrint(("NbtTdiPnp: disabling address on %wZ", &pDeviceContext->ExportName ));
  1342. NbtNewDhcpAddress(pDeviceContext, 0, 0); // Get rid of IP address to disable adapter
  1343. }
  1344. }
  1345. #endif
  1346. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, FALSE);
  1347. SetNodeType();
  1348. }
  1349. return (status);
  1350. }
  1351. //----------------------------------------------------------------------------
  1352. NTSTATUS
  1353. CheckSetWakeupPattern(
  1354. tDEVICECONTEXT *pDeviceContext,
  1355. PUCHAR pName,
  1356. BOOLEAN RequestAdd
  1357. )
  1358. {
  1359. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  1360. CTELockHandle OldIrq;
  1361. ULONG InBufLen = 0;
  1362. IP_WAKEUP_PATTERN_REQUEST IPWakeupPatternReq; // Ioctl Data Format (12 bytes)
  1363. NET_PM_WAKEUP_PATTERN_DESC WakeupPatternDesc; // IP data (8 Bytes)
  1364. NETBT_WAKEUP_PATTERN PatternData; // Data Storage for the Wakeup Data itself (72)
  1365. BOOLEAN fAttached = FALSE;
  1366. if (pDeviceContext->DeviceType != NBT_DEVICE_REGULAR)
  1367. {
  1368. return STATUS_UNSUCCESSFUL;
  1369. }
  1370. CTESpinLock(pDeviceContext,OldIrq);
  1371. //
  1372. // Only 1 pattern (the first one) can be set at any time
  1373. //
  1374. if (RequestAdd)
  1375. {
  1376. if (pDeviceContext->WakeupPatternRefCount)
  1377. {
  1378. //
  1379. // There is already a pattern registered on this device
  1380. //
  1381. if (CTEMemEqu (pDeviceContext->WakeupPatternName, pName, NETBIOS_NAME_SIZE-1))
  1382. {
  1383. pDeviceContext->WakeupPatternRefCount++;
  1384. Status = STATUS_SUCCESS;
  1385. }
  1386. CTESpinFree(pDeviceContext,OldIrq);
  1387. return (Status);
  1388. }
  1389. // This is the first pattern
  1390. CTEMemCopy(&pDeviceContext->WakeupPatternName,pName,NETBIOS_NAME_SIZE);
  1391. pDeviceContext->WakeupPatternRefCount++;
  1392. }
  1393. //
  1394. // This is a Delete pattern request
  1395. //
  1396. else
  1397. {
  1398. if ((!pDeviceContext->WakeupPatternRefCount) || // No pattern currently registered
  1399. (!CTEMemEqu (pDeviceContext->WakeupPatternName, pName, NETBIOS_NAME_SIZE-1))) // Not this pattern
  1400. {
  1401. CTESpinFree(pDeviceContext,OldIrq);
  1402. return (STATUS_UNSUCCESSFUL);
  1403. }
  1404. //
  1405. // The pattern for deletion matched the pattern that was set earlier
  1406. //
  1407. else if (--pDeviceContext->WakeupPatternRefCount)
  1408. {
  1409. //
  1410. // This pattern is still referenced
  1411. //
  1412. CTESpinFree(pDeviceContext,OldIrq);
  1413. return (STATUS_SUCCESS);
  1414. }
  1415. }
  1416. CTESpinFree(pDeviceContext,OldIrq);
  1417. IF_DBG(NBT_DEBUG_PNP_POWER)
  1418. KdPrint(("Nbt.SetWakeupPattern: %s<%-16.16s:%x> on Device=<%wZ>\n",
  1419. (RequestAdd ? "Add" : "Remove"), pName, pName[15], &pDeviceContext->BindName));
  1420. //
  1421. // Initialize the Pattern Data
  1422. //
  1423. CTEZeroMemory((PVOID) &PatternData, sizeof(NETBT_WAKEUP_PATTERN));
  1424. ConvertToHalfAscii((PCHAR) &PatternData.nbt_NameRR, pName, NULL, 0);
  1425. PatternData.iph_protocol = 0x11; // UDP Protocol
  1426. PatternData.udph_src = htons (NBT_NAMESERVICE_UDP_PORT);
  1427. PatternData.udph_dest = htons (NBT_NAMESERVICE_UDP_PORT);
  1428. PatternData.nbt_OpCodeFlags = htons (0x0010);
  1429. //
  1430. // Initialize the WakeupPattern Description
  1431. //
  1432. WakeupPatternDesc.Next = NULL;
  1433. WakeupPatternDesc.Ptrn = (PUCHAR) &PatternData;
  1434. WakeupPatternDesc.Mask = NetBTPatternMask;
  1435. WakeupPatternDesc.PtrnLen = NetBTPatternLen;
  1436. //
  1437. // Initialize the WakeupPattern Request
  1438. //
  1439. IPWakeupPatternReq.PtrnDesc = &WakeupPatternDesc;
  1440. IPWakeupPatternReq.AddPattern = RequestAdd; // Add = TRUE, Remove = FALSE
  1441. IPWakeupPatternReq.InterfaceContext = pDeviceContext->IPInterfaceContext;
  1442. //
  1443. // Now, register the Wakeup pattern on this adapter
  1444. //
  1445. Status = NbtProcessIPRequest (IOCTL_IP_WAKEUP_PATTERN,
  1446. &IPWakeupPatternReq, // Input buffer
  1447. sizeof (IP_WAKEUP_PATTERN_REQUEST),
  1448. NULL,
  1449. NULL
  1450. );
  1451. //
  1452. // If we were doing an add, we need to Deref since we failed to register this pattern
  1453. //
  1454. if ((RequestAdd) &&
  1455. (!NT_SUCCESS (Status)))
  1456. {
  1457. CTESpinLock(pDeviceContext,OldIrq);
  1458. pDeviceContext->WakeupPatternRefCount--;
  1459. CTESpinFree(pDeviceContext,OldIrq);
  1460. }
  1461. return Status;
  1462. }
  1463. /*
  1464. * bug #88696
  1465. * Set the global variable NodeType based on RegistryNodeType and WINS configuration
  1466. */
  1467. void
  1468. SetNodeType(void)
  1469. {
  1470. /* We only need to check if the registry NodeType is broadcast */
  1471. if (RegistryNodeType & (BNODE| DEFAULT_NODE_TYPE)) {
  1472. /*
  1473. * If there exist at least one active link with WINS server,
  1474. * we set NodeType to hybrid.
  1475. */
  1476. PLIST_ENTRY head, item;
  1477. CTELockHandle OldIrq;
  1478. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1479. NodeType = RegistryNodeType;
  1480. head = &NbtConfig.DeviceContexts;
  1481. for (item = head->Flink; item != head; item = item->Flink) {
  1482. tDEVICECONTEXT* dev;
  1483. dev = CONTAINING_RECORD(item, tDEVICECONTEXT, Linkage);
  1484. if (dev->IsDestroyed || dev->IpAddress == 0 ||
  1485. !dev->NetbiosEnabled) {
  1486. continue;
  1487. }
  1488. if ((dev->lNameServerAddress!=LOOP_BACK && dev->lNameServerAddress) || (dev->lBackupServer!=LOOP_BACK && dev->lBackupServer)) {
  1489. NodeType = (MSNODE | (NodeType & PROXY));
  1490. /* We don't need to check further */
  1491. break;
  1492. }
  1493. }
  1494. // A broadcast node cannot have proxy
  1495. if ((NodeType & BNODE) && (NodeType & PROXY)) {
  1496. NodeType &= (~PROXY);
  1497. }
  1498. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1499. }
  1500. }
  1501. NTSTATUS
  1502. LookupDeviceInRegistry(
  1503. IN PUNICODE_STRING pBindName,
  1504. OUT tADDRARRAY* pAddrs,
  1505. OUT PUNICODE_STRING pExportName
  1506. )
  1507. {
  1508. tDEVICES *pBindDevices = NULL;
  1509. tDEVICES *pExportDevices = NULL;
  1510. tADDRARRAY *pAddrArray = NULL;
  1511. NTSTATUS Status;
  1512. int i;
  1513. CTEPagedCode();
  1514. CTEExAcquireResourceExclusive(&NbtConfig.Resource,TRUE);
  1515. Status = NbtReadRegistry (&pBindDevices, &pExportDevices, &pAddrArray);
  1516. if (!NT_SUCCESS(Status) || !pBindDevices || !pExportDevices || !pAddrArray) {
  1517. KdPrint (("NetBT!LookupDeviceInRegistry: Registry incomplete: pBind=<%x>, pExport=<%x>, pAddrArray=<%x>\n",
  1518. pBindDevices, pExportDevices, pAddrArray));
  1519. CTEExReleaseResource(&NbtConfig.Resource);
  1520. NbtReadRegistryCleanup(&pBindDevices, &pExportDevices, &pAddrArray);
  1521. return STATUS_REGISTRY_CORRUPT;
  1522. }
  1523. Status = STATUS_UNSUCCESSFUL;
  1524. for (i=0; i<pNbtGlobConfig->uNumDevicesInRegistry; i++ ) {
  1525. if (RtlCompareUnicodeString(pBindName, &pBindDevices->Names[i], TRUE) == 0) {
  1526. Status = STATUS_SUCCESS;
  1527. if (pAddrs) {
  1528. RtlCopyMemory(pAddrs, &pAddrArray[i], sizeof(pAddrArray[i]));
  1529. }
  1530. if (pExportName) {
  1531. pExportName->MaximumLength = pExportDevices->Names[i].MaximumLength;
  1532. pExportName->Buffer = NbtAllocMem(pExportDevices->Names[i].MaximumLength, NBT_TAG2('17'));
  1533. if (pExportName->Buffer == NULL) {
  1534. KdPrint (("NetBT!LookupDeviceInRegistry: fail to allocate memory\n"));
  1535. Status = STATUS_INSUFFICIENT_RESOURCES;
  1536. } else {
  1537. RtlCopyUnicodeString(pExportName, &pExportDevices->Names[i]);
  1538. }
  1539. }
  1540. break;
  1541. }
  1542. }
  1543. NbtReadRegistryCleanup(&pBindDevices, &pExportDevices, &pAddrArray);
  1544. CTEExReleaseResource(&NbtConfig.Resource);
  1545. return Status;
  1546. }
  1547. tDEVICECONTEXT *
  1548. CheckAddrNotification(
  1549. IN PTA_ADDRESS Addr,
  1550. IN PUNICODE_STRING pDeviceName,
  1551. OUT ULONG *IpAddr
  1552. )
  1553. /*++
  1554. Check if the TDI address notification is for us,
  1555. if so, return a Referenced device context and the IP address
  1556. otherwise, return NULL.
  1557. Note: it is the caller's responsibility to dereference the device context.
  1558. --*/
  1559. {
  1560. CTEPagedCode();
  1561. if (IsIPv6Interface(pDeviceName)) {
  1562. return NULL;
  1563. }
  1564. //
  1565. // Ignore any other type of address except IP
  1566. //
  1567. if (Addr->AddressType != TDI_ADDRESS_TYPE_IP) {
  1568. return NULL;
  1569. }
  1570. *IpAddr = ntohl(((PTDI_ADDRESS_IP)&Addr->Address[0])->in_addr);
  1571. IF_DBG(NBT_DEBUG_PNP_POWER)
  1572. {
  1573. IF_DBG(NBT_DEBUG_PNP_POWER)
  1574. KdPrint(("netbt!CheckAddrNotification: %d.%d.%d.%d\n",
  1575. ((*IpAddr)>>24)&0xFF,((*IpAddr)>>16)&0xFF,((*IpAddr)>>8)&0xFF,(*IpAddr)&0xFF));
  1576. }
  1577. //
  1578. // Filter out zero address notifications
  1579. //
  1580. if (*IpAddr == 0) {
  1581. KdPrint (("Nbt.TdiAddressDeletion: ERROR: Address <%x> not assigned to any device!\n", IpAddr));
  1582. return NULL;
  1583. }
  1584. //
  1585. // Ignore this notification if we don't bind to this device
  1586. //
  1587. return NbtFindAndReferenceDevice (pDeviceName, TRUE);
  1588. }