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.

1150 lines
40 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // nbtnm.c
  8. //
  9. // Abstract:
  10. //
  11. // Queries into network drivers
  12. //
  13. // Author:
  14. //
  15. // Anilth - 4-20-1998
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. // NSun - 9-03-1998
  25. //
  26. //--
  27. #include "precomp.h"
  28. #include "dhcptest.h"
  29. const TCHAR c_szPath[] = _T("\\Device\\NetBT_Tcpip_");
  30. TCHAR pDeviceName[NBT_MAXIMUM_BINDINGS][MAX_NAME+1];
  31. TCHAR * printable( IN TCHAR * string, IN TCHAR * StrOut );
  32. //$REVIEW (nsun) previously using ReadNbtNameRegistry() see Bug 152014
  33. LONG GetInterfaceList( IN OUT TCHAR pDeviceName[][MAX_NAME+1], IN OUT PUCHAR pScope );
  34. NTSTATUS OpenNbt(IN char path[][MAX_NAME+1], OUT PHANDLE pHandle, int max_paths);
  35. NTSTATUS DeviceIoCtrl(
  36. IN HANDLE fd,
  37. IN PVOID ReturnBuffer,
  38. IN ULONG BufferSize,
  39. IN ULONG Ioctl,
  40. IN PVOID pInput,
  41. IN ULONG SizeInput
  42. );
  43. /* =======================================================================
  44. * name_type() -- describe NBT Name types
  45. *
  46. */
  47. char *
  48. name_type(int t)
  49. {
  50. if (t & GROUP_NAME) return("GROUP");
  51. else return("UNIQUE");
  52. }
  53. //-------------------------------------------------------------------------//
  54. //###### N b t N m T e s t () ###########################################//
  55. //-------------------------------------------------------------------------//
  56. // Abstract: //
  57. // Test that the names //
  58. // <00> - wks svc name = NETBIOS computer name //
  59. // <03> - messenger svc name //
  60. // <20> - server svc name //
  61. // are present on all interfaces and that they are not in conflict //
  62. // Arguments: //
  63. // none //
  64. // Return value: //
  65. // TRUE - test passed //
  66. // FALSE - test failed //
  67. // Global variables used: //
  68. // none //
  69. // Revision History: //
  70. // List remote machines cache too - Rajkumar 06/30/98 //
  71. //-------------------------------------------------------------------------//
  72. HRESULT NbtNmTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  73. {
  74. HRESULT hr = S_OK;
  75. TCHAR pScope[MAX_NAME + 1];
  76. int index;
  77. HANDLE hNbt = (HANDLE) -1;
  78. ULONG BufferSize = sizeof(tADAPTERSTATUS);
  79. PVOID pBuffer = NULL;
  80. LONG lCount;
  81. int nNameProblemCnt = 0;
  82. BOOL is00, is03, is20, isGlobal00, isGlobal03, isGlobal20;
  83. tADAPTERSTATUS *pAdapterStatus;
  84. NAME_BUFFER *pNames;
  85. NTSTATUS status;
  86. TDI_REQUEST_QUERY_INFORMATION QueryInfo;
  87. //
  88. // Variables for Netbios Name resolution option - Rajkumar
  89. //
  90. HKEY hkeyNetBTKey;
  91. HKEY hkeyNBTAdapterKey;
  92. DWORD valueType;
  93. DWORD valueLength;
  94. DWORD NetbiosOptions;
  95. INT err;
  96. //
  97. // For remote cache information
  98. //
  99. UCHAR* Addr;
  100. TCHAR HostAddr[20];
  101. //
  102. // End of changes - Rajkumar 06/17/98
  103. //
  104. PrintStatusMessage(pParams, 4, IDS_NBTNM_STATUS_MSG);
  105. //Init the global message link list
  106. InitializeListHead( &pResults->NbtNm.lmsgGlobalOutput );
  107. if (!pResults->Global.fHasNbtEnabledInterface)
  108. {
  109. AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_Verbose, IDS_NBTNM_ALL_DISABELED);
  110. return S_OK;
  111. }
  112. //
  113. // get the names of all the interfaces from the registry
  114. //
  115. if ( ERROR_SUCCESS != GetInterfaceList( pDeviceName, pScope ) )
  116. {
  117. //IDS_NBTNM_12201 " [FATAL] failed to read NBT interface info from the registry!\n"
  118. AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_Quiet, IDS_NBTNM_12201 );
  119. hr = S_FALSE;
  120. goto end_NbtNmTest;
  121. }
  122. if ( *pScope == '\0')
  123. //IDS_NBTNM_12202 " No NetBT scope defined\n"
  124. AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12202 );
  125. else
  126. //IDS_NBTNM_12203 " NetBT scope: %s\n"
  127. AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12203, pScope );
  128. //
  129. // loop through the interfaces and get the names on them
  130. //
  131. isGlobal00 = isGlobal03 = isGlobal20 = FALSE;
  132. for ( index = 0; index < NBT_MAXIMUM_BINDINGS && pDeviceName[index][0]; index++ )
  133. {
  134. LPTSTR pszAdapterName;
  135. INTERFACE_RESULT* pIfResults;
  136. UINT c03NameProblem = 0;
  137. pIfResults = NULL;
  138. //try to find a match in the current interface list
  139. //$REVIEW It seems we should always find a match here. Maybe we need print
  140. // a FAIL message if cannot find a match.
  141. if( 0 == _tcsncmp(c_szPath, pDeviceName[index], _tcslen(c_szPath)))
  142. {
  143. // LPTSTR pszAdapterName;
  144. int i;
  145. pszAdapterName = _tcsdup( pDeviceName[index] + _tcslen(c_szPath));
  146. for ( i=0; i<pResults->cNumInterfaces; i++)
  147. {
  148. if (_tcscmp(pResults->pArrayInterface[i].pszName,
  149. pszAdapterName) == 0)
  150. {
  151. pIfResults = pResults->pArrayInterface + i;
  152. break;
  153. }
  154. }
  155. Free(pszAdapterName);
  156. }
  157. if(NULL == pIfResults)
  158. {
  159. //we should be able to get the match. That is weird!
  160. DebugMessage("[WARNING] A NetBT interface is not in our TCPIP interface list!\n");
  161. // We need a new interface result structure, grab one
  162. // (if it is free), else allocate more.
  163. if (pResults->cNumInterfaces >= pResults->cNumInterfacesAllocated)
  164. {
  165. PVOID pv;
  166. // Need to do a realloc to get more memory
  167. pv = Realloc(pResults->pArrayInterface,
  168. sizeof(INTERFACE_RESULT)*(pResults->cNumInterfacesAllocated+8));
  169. if (pv == NULL)
  170. {
  171. DebugMessage(" Realloc memory failed. \n");
  172. hr = E_OUTOFMEMORY;
  173. goto end_NbtNmTest;
  174. }
  175. pResults->pArrayInterface = pv;
  176. pResults->cNumInterfacesAllocated += 8;
  177. }
  178. pIfResults = pResults->pArrayInterface + pResults->cNumInterfaces;
  179. pResults->cNumInterfaces++;
  180. ZeroMemory(pIfResults, sizeof(INTERFACE_RESULT));
  181. pIfResults->pszName = _tcsdup(pszAdapterName);
  182. pIfResults->pszFriendlyName = _tcsdup(_T("Additional NetBT interface"));
  183. pIfResults->fActive = TRUE;
  184. pIfResults->NbtNm.fActive = TRUE;
  185. pIfResults->NbtNm.fQuietOutput = FALSE;
  186. }
  187. else
  188. {
  189. pIfResults->NbtNm.fActive = pIfResults->fActive;
  190. }
  191. if(!pIfResults->NbtNm.fActive ||
  192. NETCARD_DISCONNECTED == pIfResults->dwNetCardStatus)
  193. continue;
  194. InitializeListHead( &pIfResults->NbtNm.lmsgOutput );
  195. if (!pIfResults->fNbtEnabled)
  196. {
  197. AddMessageToList(&pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_IF_DISABLED);
  198. continue;
  199. }
  200. /* //$REVIEW Can we skip WAN adapters
  201. if ( _tcsstr( pDeviceName[index], "NdisWan" ) ) {
  202. //
  203. // let's not worry about WAN interfaces yet
  204. //
  205. continue;
  206. }
  207. */
  208. // Strip off the "\Device\" off of the beginning of
  209. // the string
  210. //IDS_NBTNM_12204 " %s\n"
  211. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12204, MapGuidToServiceName(pDeviceName[index]+8));
  212. status = OpenNbt( &pDeviceName[index], &hNbt, NBT_MAXIMUM_BINDINGS - index );
  213. //
  214. // let's get the names on this interface
  215. //
  216. pBuffer = Malloc( BufferSize );
  217. if ( !pBuffer ) {
  218. DebugMessage(" [FATAL] name table buffer allocation failed!\n" );
  219. hr = E_OUTOFMEMORY;
  220. CloseHandle( hNbt );
  221. goto end_NbtNmTest;
  222. }
  223. ZeroMemory( pBuffer, BufferSize );
  224. QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever
  225. //
  226. // find the right buffer size
  227. //
  228. status = STATUS_BUFFER_OVERFLOW;
  229. while ( status == STATUS_BUFFER_OVERFLOW )
  230. {
  231. //$REVIEW there should be a better way to decide the buffer size
  232. status = DeviceIoCtrl(hNbt,
  233. pBuffer,
  234. BufferSize,
  235. IOCTL_TDI_QUERY_INFORMATION,
  236. &QueryInfo,
  237. sizeof(TDI_REQUEST_QUERY_INFORMATION)
  238. );
  239. if ( status == STATUS_BUFFER_OVERFLOW ) {
  240. Free( pBuffer );
  241. BufferSize *= 2;
  242. pBuffer = Malloc( BufferSize );
  243. if ( !pBuffer ) {
  244. DebugMessage( " [FATAL] Buffer allocation for name table retrieval failed.\n" );
  245. hr = E_OUTOFMEMORY;
  246. CloseHandle( hNbt );
  247. goto end_NbtNmTest;
  248. }
  249. ZeroMemory( pBuffer, BufferSize );
  250. }
  251. }
  252. //
  253. // at this point we have the local name table in pBuffer
  254. //
  255. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  256. if ( (pAdapterStatus->AdapterInfo.name_count == 0) ||
  257. (status != STATUS_SUCCESS) )
  258. {
  259. //IDS_NBTNM_12205 " No names have been found.\n"
  260. AddMessageToListId(&pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12205 );
  261. Free( pBuffer );
  262. CloseHandle( hNbt );
  263. continue;
  264. }
  265. pNames = pAdapterStatus->Names;
  266. lCount = pAdapterStatus->AdapterInfo.name_count;
  267. //
  268. // cycle thorugh the names
  269. //
  270. nNameProblemCnt = 0;
  271. is00 = is03 = is20 = FALSE;
  272. while( lCount-- )
  273. {
  274. TCHAR szNameOut[NETBIOS_NAME_SIZE +4];
  275. //$REVIEW (nsun) BUG227186 CliffV said problems with <03> name is not fatal.
  276. // Just need a warning message.
  277. BOOL f03Name = FALSE;
  278. if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x0 )
  279. {
  280. isGlobal00 = TRUE;
  281. is00 = TRUE;
  282. if ( !(pNames->name_flags & GROUP_NAME) ) {
  283. // unique name
  284. memcpy( nameToQry, pNames->name, (NETBIOS_NAME_SIZE-1));
  285. }
  286. }
  287. if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x3 ) {
  288. isGlobal03 = TRUE;
  289. is03 = TRUE;
  290. f03Name = TRUE;
  291. }
  292. if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x20 ) {
  293. isGlobal20 = TRUE;
  294. is20 = TRUE;
  295. }
  296. //IDS_NBTNM_12206 "\t%-15.15s<%02.2X> %-10s "
  297. AddMessageToList( &pIfResults->NbtNm.lmsgOutput,
  298. Nd_ReallyVerbose,
  299. IDS_NBTNM_12206,
  300. printable(pNames->name, szNameOut),
  301. pNames->name[NETBIOS_NAME_SIZE-1],
  302. name_type(pNames->name_flags));
  303. switch(pNames->name_flags & 0x0F)
  304. {
  305. case DUPLICATE_DEREG:
  306. //IDS_NBTNM_12207 "CONFLICT_DEREGISTERED"
  307. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12207 );
  308. if(f03Name)
  309. c03NameProblem ++;
  310. else
  311. nNameProblemCnt++;
  312. break;
  313. case DUPLICATE:
  314. //IDS_NBTNM_12208 "CONFLICT"
  315. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12208 );
  316. if(f03Name)
  317. c03NameProblem ++;
  318. else
  319. nNameProblemCnt++;
  320. break;
  321. case REGISTERING:
  322. //IDS_NBTNM_12209 "REGISTERING"
  323. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12209 );
  324. if(f03Name)
  325. c03NameProblem ++;
  326. else
  327. nNameProblemCnt++;
  328. break;
  329. case DEREGISTERED:
  330. //IDS_NBTNM_12210 "DEREGISTERED"
  331. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12210 );
  332. if(f03Name)
  333. c03NameProblem ++;
  334. else
  335. nNameProblemCnt++;
  336. break;
  337. case REGISTERED:
  338. //IDS_NBTNM_12211 "REGISTERED"
  339. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12211 );
  340. break;
  341. default:
  342. //$REVIEW Should have a PM to review words and grammar of the output message, DONT_KNOW
  343. //IDS_NBTNM_12212 "DONT_KNOW"
  344. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12212 );
  345. if(f03Name)
  346. c03NameProblem ++;
  347. else
  348. nNameProblemCnt++;
  349. break;
  350. }
  351. pNames++;
  352. //IDS_GLOBAL_EmptyLine "\n"
  353. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_GLOBAL_EmptyLine );
  354. } /* while() all the names on a given interface */
  355. if ( nNameProblemCnt != 0 )
  356. {
  357. pIfResults->NbtNm.fQuietOutput = TRUE;
  358. //if not really verbose, the device name is not printed before.
  359. if( !pParams->fReallyVerbose)
  360. {
  361. //IDS_NBTNM_12204 " %s\n"
  362. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12204, pDeviceName[index] );
  363. }
  364. //IDS_NBTNM_12214 " [FATAL] At least one of your NetBT names is not registered properly!\n"
  365. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12214 );
  366. //IDS_NBTNM_12215 " You have a potential name conflict!\n"
  367. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12215 );
  368. //IDS_NBTNM_12216 " Please check that the machine name is unique!\n"
  369. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12216 );
  370. hr = S_FALSE;
  371. }
  372. else if( c03NameProblem != 0 )
  373. {
  374. //if not really verbose, the device name is not printed before.
  375. if( !pParams->fReallyVerbose)
  376. {
  377. //IDS_NBTNM_12204 " %s\n"
  378. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12204, pDeviceName[index] );
  379. }
  380. //IDS_NBTNM_03PROBLEM " [WARNING] At least one of your <03> NetBT names is not registered properly!\n"
  381. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_03PROBLEM );
  382. }
  383. if ( !(is00 && is03 && is20) )
  384. {
  385. //if not really verbose, the device name is not printed before.
  386. if( !pParams->fReallyVerbose)
  387. {
  388. //IDS_NBTNM_12204 " %s\n"
  389. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12204, pDeviceName[index] );
  390. }
  391. //IDS_NBTNM_12217 " [WARNING] At least one of the <00>, <03>, <20> names is missing!\n"
  392. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12217 );
  393. }
  394. nNameProblemCnt = 0;
  395. if (pParams->fReallyVerbose)
  396. {
  397. err = RegOpenKey(HKEY_LOCAL_MACHINE,
  398. "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces",
  399. &hkeyNetBTKey
  400. );
  401. // if we are here , then we are working on a LAN card
  402. if( ERROR_SUCCESS != err )
  403. {
  404. DebugMessage("Error Opening \\NetBT\\Parameters\\Interfaces Key\n");
  405. goto continue_NbtNmTest;
  406. }
  407. err = RegOpenKey(hkeyNetBTKey,
  408. pDeviceName[index]+14,
  409. &hkeyNBTAdapterKey
  410. );
  411. if( ERROR_SUCCESS != err )
  412. {
  413. DebugMessage2("Error Reading Adapter %s Key\n", pDeviceName[index]+14);
  414. goto continue_NbtNmTest;
  415. }
  416. valueLength = sizeof(DWORD);
  417. err = RegQueryValueEx(hkeyNBTAdapterKey,
  418. "NetbiosOptions",
  419. NULL,
  420. &valueType,
  421. (LPBYTE)&NetbiosOptions,
  422. &valueLength
  423. );
  424. if( ERROR_SUCCESS != err)
  425. {
  426. DebugMessage("Error Reading NetbiosOptions\n");
  427. goto continue_NbtNmTest;
  428. }
  429. //IDS_NBTNM_12218 "\n NetBios Resolution : "
  430. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12218);
  431. switch( NetbiosOptions )
  432. {
  433. case 0:
  434. //IDS_NBTNM_12219 "via DHCP \n\n"
  435. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12219);
  436. break;
  437. case 1:
  438. //IDS_NBTNM_12220 "Enabled\n\n"
  439. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12220);
  440. break;
  441. case 2:
  442. //IDS_NBTNM_12221 "Disabled\n\n"
  443. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12221);
  444. break;
  445. default:
  446. //IDS_NBTNM_12222 "Invalid Option Value!\n"
  447. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12222);
  448. break;
  449. }
  450. }
  451. continue_NbtNmTest:
  452. //
  453. // Start of code changes for dumping remote machine cache entries - Rajkumar
  454. //
  455. status = STATUS_BUFFER_OVERFLOW;
  456. while ( status == STATUS_BUFFER_OVERFLOW )
  457. {
  458. status = DeviceIoCtrl(hNbt,
  459. pBuffer,
  460. BufferSize,
  461. IOCTL_NETBT_GET_REMOTE_NAMES,
  462. NULL,
  463. 0
  464. );
  465. if ( status == STATUS_BUFFER_OVERFLOW )
  466. {
  467. Free( pBuffer );
  468. BufferSize *= 2;
  469. pBuffer = Malloc( BufferSize );
  470. if ( !pBuffer || (BufferSize == 0xFFFF) )
  471. {
  472. DebugMessage( " [FATAL] Buffer allocation for name table retrieval failed.\n" );
  473. hr = E_OUTOFMEMORY;
  474. CloseHandle( hNbt );
  475. goto end_NbtNmTest;
  476. }
  477. ZeroMemory( pBuffer, BufferSize );
  478. }
  479. }
  480. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  481. if ( (pAdapterStatus->AdapterInfo.name_count == 0) ||
  482. (status != STATUS_SUCCESS)
  483. )
  484. {
  485. //IDS_NBTNM_12224 " No remote names have been found.\n"
  486. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12224 );
  487. CloseHandle( hNbt );
  488. Free( pBuffer );
  489. //$REVIEW Should we return S_FALSE here?
  490. continue;
  491. }
  492. pNames = pAdapterStatus->Names;
  493. lCount = pAdapterStatus->AdapterInfo.name_count;
  494. //IDS_NBTNM_12225 "\t\tNetbios Remote Cache Table\n"
  495. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12225);
  496. //IDS_NBTNM_12226 "\tName Type HostAddress Life [sec]\n"
  497. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12226);
  498. //IDS_NBTNM_12227 "\t--------------------------------------------------\n"
  499. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12227);
  500. if (lCount == 0)
  501. //IDS_NBTNM_12228 "\nNone\n\n"
  502. AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12228);
  503. while (lCount-- )
  504. {
  505. TCHAR szNameOut[NETBIOS_NAME_SIZE +4];
  506. //IDS_NBTNM_12229 "\t%-15.15s<%02.2X> %-10s "
  507. AddMessageToList( &pIfResults->NbtNm.lmsgOutput,
  508. Nd_ReallyVerbose,
  509. IDS_NBTNM_12229,
  510. printable(pNames->name, szNameOut),
  511. pNames->name[NETBIOS_NAME_SIZE-1],
  512. name_type(pNames->name_flags));
  513. Addr = &(UCHAR)((tREMOTE_CACHE *)pNames)->IpAddress;
  514. _stprintf( HostAddr, "%d.%d.%d.%d", Addr[3], Addr[2], Addr[1], Addr[0]);
  515. //IDS_NBTNM_12231 "%-20.20s %-d\n"
  516. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12231, HostAddr, ((tREMOTE_CACHE *)pNames)->Ttl);
  517. ((tREMOTE_CACHE *)pNames)++;
  518. }
  519. //IDS_GLOBAL_EmptyLine "\n"
  520. AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_GLOBAL_EmptyLine);
  521. Free(pBuffer);
  522. //
  523. // End of code changes
  524. //
  525. CloseHandle(hNbt);
  526. } /* for ( all the interfaces ) */
  527. if ( !(isGlobal00 && isGlobal03 && isGlobal20) )
  528. {
  529. //IDS_NBTNM_12233 " [WARNING] You don't have a single interface with the <00>, <03>, <20> names defined!\n"
  530. AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_Quiet, IDS_NBTNM_12233 );
  531. }
  532. else
  533. {
  534. //IDS_NBTNM_12234 "\n PASS - your NetBT configuration looks OK\n"
  535. AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12234 );
  536. //IDS_NBTNM_12235 " there is at least one interface where the <00>, <03>, <20>\n"
  537. AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12235 );
  538. //IDS_NBTNM_12236 " names are defined and they are not in conflict.\n"
  539. AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12236 );
  540. }
  541. end_NbtNmTest:
  542. if ( FHrOK(hr) )
  543. {
  544. PrintStatusMessage(pParams, 0, IDS_GLOBAL_PASS_NL);
  545. }
  546. else
  547. {
  548. PrintStatusMessage(pParams, 0, IDS_GLOBAL_FAIL_NL);
  549. }
  550. pResults->NbtNm.hrTestResult = hr;
  551. return hr;
  552. } /* END OF NbtNmTest() */
  553. //-------------------------------------------------------------------------//
  554. //###### O p e n N b t () ###############################################//
  555. //-------------------------------------------------------------------------//
  556. // Abstract: //
  557. // Opens a handle to the device //
  558. // Arguments: //
  559. // path - path to the driver //
  560. // pHandle - the handle that we return from this function //
  561. // max_paths - I think this is unused //
  562. // Return value: //
  563. // 0 if successful //
  564. // -1 otherwise //
  565. // Global variables used: //
  566. // none //
  567. //-------------------------------------------------------------------------//
  568. NTSTATUS
  569. OpenNbt(
  570. IN TCHAR path[][MAX_NAME+1],
  571. OUT PHANDLE pHandle,
  572. int max_paths
  573. )
  574. {
  575. HANDLE StreamHandle;
  576. OBJECT_ATTRIBUTES ObjectAttributes;
  577. IO_STATUS_BLOCK IoStatusBlock;
  578. STRING name_string;
  579. UNICODE_STRING uc_name_string;
  580. NTSTATUS status;
  581. LONG index=0;
  582. assert( max_paths <= NBT_MAXIMUM_BINDINGS );
  583. while ((path[index][0] != 0) && (index < max_paths))
  584. {
  585. RtlInitString(&name_string, path[index]);
  586. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  587. InitializeObjectAttributes(
  588. &ObjectAttributes,
  589. &uc_name_string,
  590. OBJ_CASE_INSENSITIVE,
  591. (HANDLE) NULL,
  592. (PSECURITY_DESCRIPTOR) NULL
  593. );
  594. status = NtCreateFile(
  595. &StreamHandle,
  596. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  597. &ObjectAttributes,
  598. &IoStatusBlock,
  599. NULL,
  600. FILE_ATTRIBUTE_NORMAL,
  601. FILE_SHARE_READ | FILE_SHARE_WRITE,
  602. FILE_OPEN_IF,
  603. 0,
  604. NULL,
  605. 0);
  606. RtlFreeUnicodeString(&uc_name_string);
  607. if (NT_SUCCESS(status)) {
  608. *pHandle = StreamHandle;
  609. return(status);
  610. }
  611. ++index;
  612. }
  613. return (status);
  614. } /* END OF OpenNbt() */
  615. //-------------------------------------------------------------------------//
  616. //###### D e v i c e I o C t r l () #####################################//
  617. //-------------------------------------------------------------------------//
  618. // Abstract: //
  619. // Wrapper for NtDeviceIoControlFile //
  620. // Arguments: //
  621. // Return value: //
  622. // Global variables used: //
  623. // none //
  624. //-------------------------------------------------------------------------//
  625. NTSTATUS
  626. DeviceIoCtrl(
  627. IN HANDLE fd,
  628. IN PVOID ReturnBuffer,
  629. IN ULONG BufferSize,
  630. IN ULONG Ioctl,
  631. IN PVOID pInput,
  632. IN ULONG SizeInput
  633. )
  634. {
  635. NTSTATUS status;
  636. int retval;
  637. ULONG QueryType;
  638. IO_STATUS_BLOCK iosb;
  639. status = NtDeviceIoControlFile(
  640. fd, // Handle
  641. NULL, // Event
  642. NULL, // ApcRoutine
  643. NULL, // ApcContext
  644. &iosb, // IoStatusBlock
  645. Ioctl, // IoControlCode
  646. pInput, // InputBuffer
  647. SizeInput, // InputBufferSize
  648. (PVOID) ReturnBuffer, // OutputBuffer
  649. BufferSize); // OutputBufferSize
  650. if (status == STATUS_PENDING)
  651. {
  652. status = NtWaitForSingleObject(
  653. fd, // Handle
  654. TRUE, // Alertable
  655. NULL); // Timeout
  656. if (NT_SUCCESS(status))
  657. {
  658. status = iosb.Status;
  659. }
  660. }
  661. return(status);
  662. } /* END OF DeviceIoCtrl() */
  663. //------------------------------------------------------------------------
  664. /*++
  665. Routine Description:
  666. This procedure converts non prinatble characaters to periods ('.')
  667. Arguments:
  668. string - the string to convert
  669. StrOut - ptr to a string to put the converted string into
  670. Return Value:
  671. a ptr to the string that was converted (Strout)
  672. --*/
  673. TCHAR *
  674. printable(
  675. IN TCHAR * string,
  676. IN TCHAR * StrOut
  677. )
  678. {
  679. unsigned char *Out;
  680. unsigned char *cp;
  681. LONG i;
  682. Out = StrOut;
  683. for (cp = string, i= 0; i < NETBIOS_NAME_SIZE; cp++,i++) {
  684. if (isprint(*cp)) {
  685. *Out++ = *cp;
  686. continue;
  687. }
  688. if (*cp >= 128) { /* extended characters are ok */
  689. *Out++ = *cp;
  690. continue;
  691. }
  692. *Out++ = '.';
  693. }
  694. return(StrOut);
  695. }
  696. //------------------------------------------------------------------------
  697. NTSTATUS
  698. GetInterfaceList( IN OUT TCHAR pDeviceName[][MAX_NAME+1],
  699. IN OUT PUCHAR pScope
  700. )
  701. {
  702. HANDLE StreamHandle;
  703. OBJECT_ATTRIBUTES ObjectAttributes;
  704. IO_STATUS_BLOCK IoStatusBlock;
  705. STRING name_string, AnsiString;
  706. UNICODE_STRING uc_name_string;
  707. NTSTATUS status;
  708. char pNbtWinsDeviceName[MAX_NAME] = "\\Device\\NetBt_Wins_Export";
  709. PUCHAR SubKeyParms="system\\currentcontrolset\\services\\netbt\\parameters";
  710. HKEY Key;
  711. LONG Type;
  712. ULONG size;
  713. CHAR pScopeBuffer[BUFF_SIZE];
  714. PUCHAR Scope="ScopeId";
  715. NETBT_INTERFACE_INFO *pInterfaceInfo;
  716. ULONG InterfaceInfoSize=10*sizeof(NETBT_ADAPTER_INDEX_MAP)+sizeof(ULONG);
  717. PVOID pInput = NULL;
  718. ULONG SizeInput = 0;
  719. LONG i, index=0;
  720. pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
  721. if (!pInterfaceInfo)
  722. {
  723. return(STATUS_INSUFFICIENT_RESOURCES);
  724. }
  725. RtlInitString(&name_string, pNbtWinsDeviceName);
  726. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  727. InitializeObjectAttributes(
  728. &ObjectAttributes,
  729. &uc_name_string,
  730. OBJ_CASE_INSENSITIVE,
  731. (HANDLE) NULL,
  732. (PSECURITY_DESCRIPTOR) NULL
  733. );
  734. status = NtCreateFile (&StreamHandle,
  735. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  736. &ObjectAttributes,
  737. &IoStatusBlock,
  738. NULL,
  739. FILE_ATTRIBUTE_NORMAL,
  740. FILE_SHARE_READ | FILE_SHARE_WRITE,
  741. FILE_OPEN_IF,
  742. 0,
  743. NULL,
  744. 0);
  745. RtlFreeUnicodeString(&uc_name_string);
  746. if (NT_SUCCESS (status))
  747. {
  748. do
  749. {
  750. status = DeviceIoCtrl(StreamHandle,
  751. pInterfaceInfo,
  752. InterfaceInfoSize,
  753. IOCTL_NETBT_GET_INTERFACE_INFO,
  754. pInput,
  755. SizeInput);
  756. if (status == STATUS_BUFFER_OVERFLOW)
  757. {
  758. LocalFree(pInterfaceInfo);
  759. InterfaceInfoSize *=2;
  760. pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
  761. if (!pInterfaceInfo || (InterfaceInfoSize == 0xFFFF))
  762. {
  763. NtClose(StreamHandle);
  764. DebugMessage("\nUnable to allocate packet");
  765. return(STATUS_INSUFFICIENT_RESOURCES);
  766. }
  767. }
  768. else if (!NT_SUCCESS (status))
  769. {
  770. NtClose(StreamHandle);
  771. return(status);
  772. }
  773. } while (status == STATUS_BUFFER_OVERFLOW);
  774. NtClose (StreamHandle);
  775. for (i=0; i<pInterfaceInfo->NumAdapters; i++)
  776. {
  777. RtlInitString(&name_string, NULL);
  778. RtlInitUnicodeString(&uc_name_string, pInterfaceInfo->Adapter[i].Name);
  779. if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name_string, &uc_name_string, TRUE)))
  780. {
  781. size = (name_string.Length > MAX_NAME) ? MAX_NAME : name_string.Length;
  782. strncpy(pDeviceName[index], name_string.Buffer, size);
  783. pDeviceName[index][size] = '\0';
  784. RtlFreeAnsiString (&name_string);
  785. index++;
  786. }
  787. }
  788. LocalFree(pInterfaceInfo);
  789. //
  790. // NULL out the next device string ptr
  791. //
  792. if (index < NBT_MAXIMUM_BINDINGS)
  793. {
  794. pDeviceName[index][0] = '\0';
  795. }
  796. //
  797. // Read the ScopeId key!
  798. //
  799. size = BUFF_SIZE;
  800. *pScope = '\0'; // By default
  801. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  802. SubKeyParms,
  803. 0,
  804. KEY_READ,
  805. &Key);
  806. if (status == ERROR_SUCCESS)
  807. {
  808. // now read the Scope key
  809. status = RegQueryValueEx(Key, Scope, NULL, &Type, pScopeBuffer, &size);
  810. if (status == ERROR_SUCCESS)
  811. {
  812. strcpy(pScope,pScopeBuffer);
  813. }
  814. status = RegCloseKey(Key);
  815. }
  816. status = STATUS_SUCCESS;
  817. }
  818. return status;
  819. }
  820. /*
  821. //-------------------------------------------------------------------------//
  822. //###### R e a d R e g i s t r y () #####################################//
  823. //-------------------------------------------------------------------------//
  824. // Abstract: //
  825. // Reads the names of the NetBT devices and the NetBT scope name form //
  826. // the registry. The names are stored in the Linkage/Export section //
  827. // under the NetBT key. //
  828. // Arguments: //
  829. // pScope - buffer where to store the scope string //
  830. // Return value: //
  831. // 0 if successful //
  832. // -1 otherwise //
  833. // Global variables used: //
  834. // none //
  835. //-------------------------------------------------------------------------//
  836. LONG ReadNbtNameRegistry( IN OUT TCHAR pDeviceName[][MAX_NAME+1],
  837. IN OUT PUCHAR pScope )
  838. {
  839. LPCTSTR c_szSubKeyParams = _T("system\\currentcontrolset\\services\\netbt\\parameters");
  840. LPCTSTR c_szSubKeyLinkage = _T("system\\currentcontrolset\\services\\netbt\\linkage");
  841. HKEY Key;
  842. LPCTSTR c_szScope = _T("ScopeId");
  843. LPCTSTR c_szExport = _T("Export");
  844. DWORD dwType;
  845. LONG status;
  846. LONG status2;
  847. DWORD size;
  848. LPBYTE pBuffer;
  849. size = BUFF_SIZE;
  850. status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  851. c_szSubKeyLinkage,
  852. 0,
  853. KEY_READ,
  854. &Key
  855. );
  856. if ( ERROR_SUCCESS != status)
  857. {
  858. return status;
  859. }
  860. // now read the Export values
  861. status = RegQueryValueEx( Key,
  862. c_szExport,
  863. NULL,
  864. &dwType,
  865. NULL,
  866. &size
  867. );
  868. pBuffer = Malloc(size);
  869. if( NULL == pBuffer)
  870. {
  871. DebugMessage("Out of Memory!\n");
  872. return ERROR_NOT_ENOUGH_MEMORY;
  873. }
  874. ZeroMemory( pBuffer, size );
  875. status = RegQueryValueEx( Key,
  876. c_szExport,
  877. NULL,
  878. &dwType,
  879. pBuffer,
  880. &size
  881. );
  882. if ( ERROR_SUCCESS != status)
  883. {
  884. RegCloseKey(Key);
  885. return status;
  886. }
  887. if ( status == ERROR_SUCCESS )
  888. {
  889. LPBYTE curPtr = pBuffer;
  890. LONG index = 0;
  891. //
  892. // Copy over all the export keys
  893. //
  894. while( (*curPtr) && (index < NBT_MAXIMUM_BINDINGS) )
  895. {
  896. _tcscpy( pDeviceName[index], curPtr );
  897. ++index;
  898. curPtr += strlen(curPtr) + 1;
  899. }
  900. //
  901. // NULL out the next device string ptr
  902. //
  903. if ( index < NBT_MAXIMUM_BINDINGS ) {
  904. pDeviceName[index][0] = 0;
  905. }
  906. }
  907. Free(pBuffer);
  908. status = RegCloseKey( Key );
  909. if ( status != ERROR_SUCCESS )
  910. DebugMessage("Error closing the Registry key\n");
  911. status2 = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  912. c_szSubKeyParams,
  913. 0,
  914. KEY_READ,
  915. &Key
  916. );
  917. if ( status2 == ERROR_SUCCESS )
  918. {
  919. // now read the linkage values
  920. status2 = RegQueryValueEx( Key,
  921. c_szScope,
  922. NULL,
  923. &dwType,
  924. pScope,
  925. &size
  926. );
  927. if( ERROR_SUCCESS != status2)
  928. {
  929. // No ScopeId!
  930. *pScope = 0;
  931. }
  932. status2 = RegCloseKey(Key);
  933. }
  934. return status;
  935. }
  936. */
  937. void NbtNmGlobalPrint(IN NETDIAG_PARAMS *pParams,
  938. IN OUT NETDIAG_RESULT *pResults)
  939. {
  940. if (pParams->fVerbose || pResults->NbtNm.hrTestResult != S_OK)
  941. {
  942. PrintNewLine(pParams, 2);
  943. PrintTestTitleResult(pParams,
  944. IDS_NBTNM_LONG,
  945. IDS_NBTNM_SHORT,
  946. pResults->Global.fHasNbtEnabledInterface ? TRUE : FALSE,
  947. pResults->NbtNm.hrTestResult, 0);
  948. }
  949. PrintMessageList(pParams, &pResults->NbtNm.lmsgGlobalOutput);
  950. }
  951. void NbtNmPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
  952. IN OUT NETDIAG_RESULT *pResults,
  953. IN INTERFACE_RESULT *pIfResults)
  954. {
  955. if (!pIfResults->NbtNm.fActive ||
  956. NETCARD_DISCONNECTED == pIfResults->dwNetCardStatus)
  957. return;
  958. if(pParams->fVerbose || pIfResults->NbtNm.fQuietOutput)
  959. {
  960. PrintTestTitleResult(pParams,
  961. IDS_NBTNM_LONG,
  962. IDS_NBTNM_SHORT,
  963. pIfResults->fNbtEnabled ? TRUE : FALSE,
  964. pResults->NbtNm.hrTestResult, 8);
  965. }
  966. PrintMessageList(pParams, &pIfResults->NbtNm.lmsgOutput);
  967. }
  968. void NbtNmCleanup(IN NETDIAG_PARAMS *pParams,
  969. IN OUT NETDIAG_RESULT *pResults)
  970. {
  971. int i;
  972. MessageListCleanUp(&pResults->NbtNm.lmsgGlobalOutput);
  973. for(i = 0; i < pResults->cNumInterfaces; i++)
  974. {
  975. if(pResults->pArrayInterface[i].NbtNm.fActive)
  976. MessageListCleanUp(&pResults->pArrayInterface[i].NbtNm.lmsgOutput);
  977. }
  978. }