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.

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