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.

997 lines
28 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. netbtkd.c
  5. Abstract:
  6. NETBT kd extension
  7. Author:
  8. Jiandong Ruan July 2000
  9. Notes:
  10. This version is totally rewritten to support 32-bit and 64-bit debug by using
  11. new features of WINDBG
  12. Revision History:
  13. 11-Jul-2000 jruan Support both 32-bit and 64-bit.
  14. --*/
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #define KDEXTMODE
  18. #define KDEXT_64BIT
  19. #include <nturtl.h>
  20. #include <ntverp.h>
  21. #include <windef.h>
  22. #include <winbase.h>
  23. #include <wdbgexts.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <..\..\inc\types.h>
  28. #define PRINTF dprintf
  29. #define ERROR dprintf
  30. EXT_API_VERSION ApiVersion = {
  31. (VER_PRODUCTVERSION_W >> 8), (VER_PRODUCTVERSION_W & 0xff),
  32. EXT_API_VERSION_NUMBER64, 0
  33. };
  34. WINDBG_EXTENSION_APIS ExtensionApis;
  35. USHORT SavedMajorVersion;
  36. USHORT SavedMinorVersion;
  37. BOOLEAN ChkTarget;
  38. ULONG64 ConfigPtr;
  39. static char* inet_addr(ULONG ip, char* addr);
  40. DECLARE_API(init)
  41. {
  42. ReloadSymbols("netbt.sys");
  43. if (*args) {
  44. ConfigPtr = GetExpression(args);
  45. } else {
  46. ConfigPtr = GetExpression("netbt!NbtConfig");
  47. }
  48. if (ConfigPtr == 0) {
  49. PRINTF ("Error -- please fix symbol path for NETBT\n");
  50. return;
  51. }
  52. return;
  53. }
  54. __inline
  55. ULONG
  56. read_list_entry(
  57. ULONG64 addr,
  58. PLIST_ENTRY64 List
  59. )
  60. {
  61. if (InitTypeRead(addr, LIST_ENTRY)) {
  62. return 1;
  63. }
  64. List->Flink = ReadField(Flink);
  65. List->Blink = ReadField(Blink);
  66. return 0;
  67. }
  68. #define READLISTENTRY read_list_entry
  69. /*++
  70. Call callback for each entry in the list
  71. --*/
  72. typedef BOOL (*LIST_FOR_EACH_CALLBACK)(ULONG64 address, PVOID);
  73. int
  74. ListForEach(ULONG64 address, int maximum, PVOID pContext, LIST_FOR_EACH_CALLBACK callback)
  75. {
  76. LIST_ENTRY64 list;
  77. int i;
  78. if (READLISTENTRY(address, &list)) {
  79. PRINTF ("Failed to read memory 0x%I64lx\n", address);
  80. return (-1);
  81. }
  82. if (list.Flink == address) {
  83. return (-1);
  84. }
  85. if (maximum < 0) {
  86. maximum = 1000000;
  87. }
  88. for (i = 0; i < maximum && (list.Flink != address); i++) {
  89. /*
  90. * Allow user to break us.
  91. */
  92. if (CheckControlC()) {
  93. break;
  94. }
  95. callback(list.Flink, pContext);
  96. if (READLISTENTRY(list.Flink, &list)) {
  97. PRINTF ("Failed to read memory 0x%I64lx\n", list.Flink);
  98. return (-1);
  99. }
  100. }
  101. return i;
  102. }
  103. #define NL 1
  104. #define NONL 0
  105. #define MAX_LIST_ELEMENTS 4096
  106. #define DEFAULT_UNICODE_DATA_LENGTH 4096
  107. USHORT s_UnicodeStringDataLength = DEFAULT_UNICODE_DATA_LENGTH;
  108. WCHAR s_UnicodeStringData[DEFAULT_UNICODE_DATA_LENGTH];
  109. WCHAR *s_pUnicodeStringData = s_UnicodeStringData;
  110. #define DEFAULT_ANSI_DATA_LENGTH 4096
  111. USHORT s_AnsiStringDataLength = DEFAULT_ANSI_DATA_LENGTH;
  112. CHAR s_AnsiStringData[DEFAULT_ANSI_DATA_LENGTH];
  113. CHAR *s_pAnsiStringData = s_AnsiStringData;
  114. LPSTR Extensions[] = {
  115. "Netbt debugger extensions",
  116. 0
  117. };
  118. LPSTR LibCommands[] = {
  119. "help -- print out these messages",
  120. "init <nbtconfig address> -- Reload symbols for NETBT.SYS",
  121. "\tinit get the address of netbt!nbtconfig which will be used by other netbt kdext commands.",
  122. "\tIn case that the symbol table cannot be loaded, you can manually set the address.",
  123. "\tExamples:",
  124. "\t\tinit --- reload symbols and automatically find the address of netbt!nbtconfig",
  125. "\t\tinit 0xfac30548 --- Force 0xfac30548 to be the address of netbt!nbtconfig",
  126. "dump -- is no longer supported. Please use 'dt <type> <addr>' instead",
  127. "\tFor example 'dt netbt!tDEVICECONTEXT 0x98765432'",
  128. "devices -- list all devices",
  129. "dev <devobj> -- dump a device",
  130. "connections -- list all connections",
  131. "cache [Local|Remote]",
  132. "localname <tNAMEADDR> Display the connections associated with a local name",
  133. "verifyll <ListHead> [<Verify>]",
  134. "sessionhdr <session header> Dump the session HDR",
  135. 0
  136. };
  137. BOOL
  138. help(void)
  139. {
  140. int i;
  141. for( i=0; Extensions[i]; i++ )
  142. PRINTF( " %s\n", Extensions[i] );
  143. for( i=0; LibCommands[i]; i++ )
  144. PRINTF( " %s\n", LibCommands[i] );
  145. return TRUE;
  146. }
  147. DECLARE_API(version)
  148. {
  149. #if DBG
  150. PCHAR DebuggerType = "Checked";
  151. #else
  152. PCHAR DebuggerType = "Free";
  153. #endif
  154. PRINTF ( "NETBT: %s extension dll (build %d) debugging %s kernel (build %d)\n",
  155. DebuggerType,
  156. VER_PRODUCTBUILD,
  157. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  158. SavedMinorVersion
  159. );
  160. }
  161. #define NAME_DELIMITER '@'
  162. #define NAME_DELIMITERS "@ "
  163. #define INVALID_INDEX 0xffffffff
  164. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  165. void
  166. dump_device(ULONG64 addr)
  167. {
  168. ULONG linkage_offset = 0;
  169. ULONG tag;
  170. ULONG ip, subnet_mask, assigned_ip, name_server1, name_server2;
  171. UCHAR mac[6];
  172. if (GetFieldOffset("netbt!tDEVICECONTEXT", (LPSTR)"Linkage", &linkage_offset)) {
  173. PRINTF ("Error -- please fix symbol path for NETBT\n");
  174. return;
  175. }
  176. InitTypeRead(addr, netbt!tDEVICECONTEXT);
  177. tag = (ULONG)ReadField(Verify);
  178. if (tag != NBT_VERIFY_DEVCONTEXT && tag != NBT_VERIFY_DEVCONTEXT_DOWN) {
  179. addr -= linkage_offset;
  180. InitTypeRead(addr, netbt!tDEVICECONTEXT);
  181. tag = (ULONG)ReadField(Verify);
  182. if (tag != NBT_VERIFY_DEVCONTEXT && tag != NBT_VERIFY_DEVCONTEXT_DOWN) {
  183. PRINTF ("Tag not found. %I64lx may not be a valid NETBT device\n", addr + linkage_offset);
  184. return;
  185. }
  186. }
  187. PRINTF ("+++++++++++++++ tDEVICECONTEXT @ %I64lx (%s) ++++++++++++++++\n",
  188. addr, (tag == NBT_VERIFY_DEVCONTEXT)? "Active": "Down");
  189. ip = (ULONG)ReadField(IpAddress);
  190. assigned_ip = (ULONG)ReadField(AssignedIpAddress);
  191. subnet_mask = (ULONG)ReadField(SubnetMask);
  192. GetFieldData(addr, "netbt!tDEVICECONTEXT", "MacAddress", 6, mac);
  193. PRINTF (" IP Address: %s\n", inet_addr(ip, NULL));
  194. PRINTF ("IP Interface Flag: %I64lx\n", ReadField(IpInterfaceFlags));
  195. PRINTF (" MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  196. PRINTF (" subnet: %s\n", inet_addr(subnet_mask & ip, NULL));
  197. if (ip != assigned_ip) {
  198. PRINTF (" Assigned Address: %s\n", inet_addr(assigned_ip, NULL));
  199. }
  200. PRINTF (" subnet mask: %s\n", inet_addr(subnet_mask, NULL));
  201. PRINTF ("broadcast address: %s\n", inet_addr((ULONG)ReadField(BroadcastAddress), NULL));
  202. PRINTF (" network mask: %s\n", inet_addr((ULONG)ReadField(NetMask), NULL));
  203. name_server1 = (ULONG)ReadField(lNameServerAddress);
  204. name_server2 = (ULONG)ReadField(lBackupServer);
  205. if (name_server1 == 0) {
  206. PRINTF (" WINS: <not configured>\n");
  207. } else if (name_server2 == 0) {
  208. PRINTF (" WINS: %s\n", inet_addr(name_server1, NULL));
  209. } else {
  210. if (ReadField(SwitchedToBackup)) {
  211. PRINTF (" Primary WINS: %s\n", inet_addr(name_server2, NULL));
  212. PRINTF (" Secondary WINS: %s (in use)\n", inet_addr(name_server1, NULL));
  213. } else {
  214. PRINTF (" Primary WINS: %s (in use)\n", inet_addr(name_server1, NULL));
  215. PRINTF (" Secondary WINS: %s\n", inet_addr(name_server2, NULL));
  216. }
  217. }
  218. if (ReadField(WinsIsDown)) {
  219. PRINTF ("************* WINS(s) ARE DOWN ***************\n");
  220. }
  221. PRINTF (" pFileObject: %I64lx (type netbt!tFILE_OBJECTS)\n", ReadField(pFileObjects));
  222. PRINTF ("TCP Session: HANDLE=%I64lx DeviceObject=%I64lx FileObject=%I64lx\n",
  223. ReadField(hSession), ReadField(pSessionDeviceObject), ReadField(pSessionFileObject));
  224. PRINTF ("TCP Control: HANDLE=%I64lx DeviceObject=%I64lx FileObject=%I64lx\n",
  225. ReadField(hControl), ReadField(pControlDeviceObject), ReadField(pControlFileObject));
  226. PRINTF ("\n");
  227. }
  228. /*++
  229. Dump a NETBT device
  230. --*/
  231. DECLARE_API (dev)
  232. {
  233. if (*args == 0) {
  234. return;
  235. }
  236. dump_device(GetExpression(args));
  237. }
  238. /*++
  239. Dump all NETBT devices
  240. --*/
  241. DECLARE_API (devices)
  242. {
  243. ULONG64 NbtSmbDevice;
  244. ULONG Offset;
  245. USHORT AdapterCounter;
  246. int num;
  247. GetFieldValue(ConfigPtr, "netbt!tNBTCONFIG", "AdapterCount", AdapterCounter);
  248. /*
  249. * SMB device
  250. */
  251. NbtSmbDevice = GetExpression("netbt!pNbtSmbDevice");
  252. ReadPtr(NbtSmbDevice, &NbtSmbDevice);
  253. PRINTF( "Dumping SMB device\n");
  254. dump_device(NbtSmbDevice);
  255. /*
  256. * dump device list
  257. */
  258. if (GetFieldOffset("netbt!tNBTCONFIG", (LPSTR)"DeviceContexts", &Offset)) {
  259. PRINTF ("Error -- please fix symbol path for NETBT\n");
  260. return;
  261. }
  262. num = ListForEach(ConfigPtr + Offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)dump_device);
  263. PRINTF ("Total devices = %d (include SMB device)\n", num + 1);
  264. /*
  265. * Check consistency
  266. */
  267. if (num != AdapterCounter) {
  268. PRINTF ("Inconsistent!!! Number of devices = %d in NbtConfig.AdapterCount\n", AdapterCounter);
  269. }
  270. }
  271. /*
  272. * call back function for dumping a list of listening request
  273. */
  274. BOOL
  275. listen_callback(ULONG64 addr, PVOID pContext)
  276. {
  277. ULONG irp_offset;
  278. ULONG linkage_offset;
  279. ULONG64 irp_addr;
  280. if (GetFieldOffset("netbt!tLISTENREQUESTS", (LPSTR)"pIrp", &irp_offset)) {
  281. PRINTF ("Error -- please fix symbol path for NETBT\n");
  282. return FALSE;
  283. }
  284. if (GetFieldOffset("netbt!tLISTENREQUESTS", (LPSTR)"Linkage", &linkage_offset)) {
  285. PRINTF ("Error -- please fix symbol path for NETBT\n");
  286. return FALSE;
  287. }
  288. addr -= linkage_offset;
  289. if (ReadPtr(addr+irp_offset, &irp_addr)) {
  290. PRINTF ("Error -- please fix symbol path for NETBT\n");
  291. return FALSE;
  292. }
  293. PRINTF ("\t\t ** pListen@<%I64lx> ==> pIrp = %I64lx\n", addr, irp_addr);
  294. return TRUE;
  295. }
  296. /*
  297. * call back function for dumping a list of connection element
  298. */
  299. BOOL
  300. connect_callback(ULONG64 addr, PVOID pContext)
  301. {
  302. ULONG linkage_offset;
  303. UCHAR name[NETBIOS_NAME_SIZE];
  304. if (GetFieldOffset("netbt!tCONNECTELE", (LPSTR)"Linkage", &linkage_offset)) {
  305. PRINTF ("Error -- please fix symbol path for NETBT\n");
  306. return FALSE;
  307. }
  308. addr -= linkage_offset;
  309. if (GetFieldData(addr, "netbt!tCONNECTELE", "RemoteName", NETBIOS_NAME_SIZE, name)) {
  310. PRINTF ("Error -- please fix symbol path for NETBT\n");
  311. return FALSE;
  312. }
  313. PRINTF ("\t\t ** Connection@<%I64lx> ==> <%-15.15s:%x>\n", addr, name, name[15]&0xff);
  314. return TRUE;
  315. }
  316. /*
  317. * call back function for dumping a list of client element
  318. */
  319. BOOL
  320. client_callback(ULONG64 addr, PVOID pContext)
  321. {
  322. ULONG connect_offset;
  323. ULONG listen_offset;
  324. ULONG active_connect_offset;
  325. ULONG linkage_offset, tag;
  326. UCHAR name[NETBIOS_NAME_SIZE];
  327. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"Linkage", &linkage_offset)) {
  328. PRINTF ("Error -- please fix symbol path for NETBT\n");
  329. return FALSE;
  330. }
  331. addr -= linkage_offset;
  332. if (InitTypeRead(addr, netbt!tCLIENTELE)) {
  333. PRINTF ("Error -- please fix symbol path for NETBT\n");
  334. return FALSE;
  335. }
  336. tag = (ULONG)ReadField(Verify);
  337. if (tag == NBT_VERIFY_CLIENT) {
  338. PRINTF ("\tActive ");
  339. } else if (tag == NBT_VERIFY_CLIENT_DOWN) {
  340. PRINTF ("\tClosed ");
  341. } else {
  342. PRINTF ("\tClient @ %I64lx: bad client tag: %lx\n", addr, tag);
  343. return FALSE;
  344. }
  345. if (GetFieldData(addr, "netbt!tCLIENTELE", "EndpointName", NETBIOS_NAME_SIZE, name)) {
  346. PRINTF ("Error -- please fix symbol path for NETBT\n");
  347. return FALSE;
  348. }
  349. PRINTF ("Client@<%I64lx> ==> pDevice = %I64lx\tEndpoint=<%-15.15s:%x>\n",
  350. addr, ReadField(pDeviceContext), name, name[15]);
  351. /*
  352. * dump the connection associated with the client element
  353. */
  354. PRINTF ("\t\t(ConnectHead):\n");
  355. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ConnectHead", &connect_offset)) {
  356. PRINTF ("Error -- please fix symbol path for NETBT\n");
  357. return FALSE;
  358. }
  359. ListForEach(addr + connect_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)connect_callback);
  360. PRINTF ("\t\t(ConnectActive)\n");
  361. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ConnectActive", &active_connect_offset)) {
  362. PRINTF ("Error -- please fix symbol path for NETBT\n");
  363. return FALSE;
  364. }
  365. ListForEach(addr + active_connect_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)connect_callback);
  366. PRINTF ("\t\t(ListenHead):\n");
  367. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ListenHead", &listen_offset)) {
  368. PRINTF ("Error -- please fix symbol path for NETBT\n");
  369. return FALSE;
  370. }
  371. ListForEach(addr + listen_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)listen_callback);
  372. PRINTF ("\n");
  373. return TRUE;
  374. }
  375. /*
  376. * call back function for dumping a list of address element
  377. */
  378. BOOL
  379. addresses_callback(ULONG64 addr, PVOID pContext)
  380. {
  381. UCHAR name[NETBIOS_NAME_SIZE];
  382. ULONG64 NameAddr;
  383. ULONG tag, linkage_offset, client_offset;
  384. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"Linkage", &linkage_offset)) {
  385. PRINTF ("Error -- please fix symbol path for NETBT: %d of %s\n", __LINE__, __FILE__);
  386. return FALSE;
  387. }
  388. addr -= linkage_offset;
  389. if (InitTypeRead(addr, netbt!tADDRESSELE)) {
  390. PRINTF ("Error -- please fix symbol path for NETBT: %I64lx\n", addr);
  391. return FALSE;
  392. }
  393. tag = (ULONG)ReadField(Verify);
  394. /*
  395. * Check tag
  396. */
  397. if (tag != NBT_VERIFY_ADDRESS) {
  398. PRINTF ("ERROR: incorrect tag <%4.4s>. %lx is properly not a address element\n", tag, addr);
  399. return FALSE;
  400. }
  401. /*
  402. * Print out the address element
  403. */
  404. NameAddr = ReadField(pNameAddr);
  405. if (GetFieldData(NameAddr, "netbt!tNAMEADDR", "Name", NETBIOS_NAME_SIZE, name)) {
  406. PRINTF ("Error -- please fix symbol path for NETBT: pNameAddr=%I64lx\n", NameAddr);
  407. return FALSE;
  408. }
  409. PRINTF ("Address@<%I64lx> ==> <%-15.15s:%x>\n", addr, name, name[15]);
  410. /*
  411. * dump the client element associated with the address element
  412. */
  413. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"ClientHead", &client_offset)) {
  414. PRINTF ("Error -- please fix symbol path for NETBT: %I64lx\n", addr);
  415. return FALSE;
  416. }
  417. ListForEach(addr + client_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)client_callback);
  418. return TRUE;
  419. }
  420. DECLARE_API(connections)
  421. {
  422. ULONG Offset;
  423. if (GetFieldOffset("netbt!tNBTCONFIG", (LPSTR)"AddressHead", &Offset)) {
  424. PRINTF ("Error -- please fix symbol path for NETBT\n");
  425. return;
  426. }
  427. PRINTF ("Dumping information on all NetBT conections ...\n");
  428. ListForEach(ConfigPtr + Offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)addresses_callback);
  429. PRINTF( "---------------- End of Connections ----------------\n");
  430. }
  431. char* inet_addr(ULONG ip, char* addr)
  432. {
  433. static char my_addr[16];
  434. if (addr == NULL) {
  435. addr = my_addr;
  436. }
  437. sprintf (addr, "%d.%d.%d.%d",
  438. (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
  439. return addr;
  440. }
  441. WCHAR*
  442. GetUnicodeString(ULONG64 addr)
  443. {
  444. USHORT length;
  445. ULONG readed_bytes;
  446. ULONG64 buffer = 0;
  447. WCHAR *p;
  448. InitTypeRead(addr, netbt!UNICODE_STRING);
  449. length = (USHORT)ReadField(Length);
  450. buffer = ReadField(Buffer);
  451. if (buffer == 0 || length == 0) {
  452. return NULL;
  453. }
  454. p = (WCHAR*)LocalAlloc(LMEM_FIXED, length + sizeof(WCHAR));
  455. if (p == NULL) {
  456. return NULL;
  457. }
  458. ReadMemory(buffer, (PVOID)p, length, &readed_bytes);
  459. if ((USHORT)readed_bytes != length) {
  460. LocalFree(p);
  461. return NULL;
  462. }
  463. p[length/sizeof(WCHAR)] = L'\0';
  464. return p;
  465. }
  466. /*
  467. * call back function for dumping a list of cache entries
  468. */
  469. BOOL
  470. cache_callback(ULONG64 addr, const int *bkt)
  471. {
  472. static ULONG addr_offset = (ULONG)(-1);
  473. static ULONG fqdn_offset = (ULONG)(-1);
  474. ULONG Verify;
  475. UCHAR name[NETBIOS_NAME_SIZE];
  476. ULONG ip, refcnt, state, ttl;
  477. WCHAR *fqdn = NULL;
  478. if (addr_offset == (ULONG)(-1)) {
  479. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"Linkage", &addr_offset)) {
  480. PRINTF ("Error -- please fix symbol path for NETBT\n");
  481. addr_offset = (ULONG)(-1);
  482. return FALSE;
  483. }
  484. }
  485. if (fqdn_offset == (ULONG)(-1)) {
  486. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"FQDN", &fqdn_offset)) {
  487. fqdn_offset = (ULONG)(-1);
  488. }
  489. }
  490. addr -= addr_offset;
  491. if (InitTypeRead(addr, netbt!tNAMEADDR)) {
  492. PRINTF ("Error -- please fix symbol path for NETBT\n");
  493. return FALSE;
  494. }
  495. Verify = (ULONG)ReadField(Verify);
  496. if (Verify != LOCAL_NAME && Verify != REMOTE_NAME) {
  497. PRINTF ("ERROR: bad name cache entry @ %I64x tag %lx!\n", addr, Verify);
  498. return FALSE;
  499. }
  500. ip = (ULONG)ReadField(IpAddress);
  501. refcnt = (ULONG)ReadField(RefCount);
  502. state = (ULONG)ReadField(NameTypeState);
  503. ttl = (ULONG)ReadField(Ttl);
  504. if (GetFieldData(addr, "netbt!tNAMEADDR", "Name", NETBIOS_NAME_SIZE, name)) {
  505. PRINTF ("Error -- please fix symbol path for NETBT\n");
  506. return FALSE;
  507. }
  508. if (fqdn_offset != (ULONG)(-1)) {
  509. fqdn = GetUnicodeString(addr + fqdn_offset);
  510. }
  511. PRINTF ("[%d]\t<%16.16I64lx> => <%-15.15s:%2x> | %-15.15s | %d | %8x | %9d\n",
  512. *bkt, addr, name, name[15], inet_addr(ip, NULL), refcnt, state, ttl);
  513. if (fqdn != NULL) {
  514. PRINTF("\t\t%ws\n", fqdn);
  515. LocalFree(fqdn);
  516. fqdn = NULL;
  517. }
  518. PRINTF("\t\tName State:");
  519. if (state & NAMETYPE_QUICK) {
  520. PRINTF(" QUICK");
  521. }
  522. if (state & NAMETYPE_UNIQUE) {
  523. PRINTF(" UNIQUE");
  524. }
  525. if (state & NAMETYPE_GROUP) {
  526. PRINTF(" GROUP");
  527. }
  528. if (state & NAMETYPE_INET_GROUP) {
  529. PRINTF(" INET_GROUP");
  530. }
  531. if (state & STATE_RESOLVED) {
  532. PRINTF(" RESOLVED");
  533. }
  534. if (state & STATE_RELEASED) {
  535. PRINTF(" RELEASED");
  536. }
  537. if (state & STATE_CONFLICT) {
  538. PRINTF(" CONFLICT");
  539. }
  540. if (state & STATE_RESOLVING) {
  541. PRINTF(" RESOLVING");
  542. }
  543. if (state & REFRESH_FAILED) {
  544. PRINTF(" REFRESH_FAILED");
  545. }
  546. if (state & PRELOADED) {
  547. PRINTF(" PRELOADED");
  548. }
  549. PRINTF("\n");
  550. return TRUE;
  551. }
  552. void
  553. dump_cache(ULONG64 addr)
  554. {
  555. LONG bucket_number;
  556. int i;
  557. static ULONG buckets_offset = (ULONG)(-1);
  558. static ULONG sizeof_list;
  559. if (buckets_offset == (ULONG)(-1)) {
  560. if (GetFieldOffset("netbt!tHASHTABLE", (LPSTR)"Bucket", &buckets_offset)) {
  561. PRINTF ("\nError -- please fix symbol path for NETBT\n");
  562. return;
  563. }
  564. sizeof_list = GetTypeSize ("LIST_ENTRY");
  565. }
  566. if (InitTypeRead(addr, netbt!tHASHTABLE)) {
  567. PRINTF ("\nError -- please fix symbol path for NETBT\n");
  568. return;
  569. }
  570. bucket_number = (ULONG) ReadField(lNumBuckets);
  571. PRINTF (" %d buckets\n", bucket_number);
  572. PRINTF ("[Bkt#]\t< Address > => <Name > | IpAddr | RefC | State | Ttl\n");
  573. for (i=0; i < bucket_number; i++) {
  574. ListForEach(addr + buckets_offset + i * sizeof_list, -1, &i, (LIST_FOR_EACH_CALLBACK)cache_callback);
  575. }
  576. PRINTF ("-----------------------------------------------------------------------------------\n");
  577. }
  578. DECLARE_API (cache)
  579. {
  580. ULONG64 local_addr, remote_addr;
  581. if (InitTypeRead(ConfigPtr, netbt!tNBTCONFIG)) {
  582. PRINTF ("Error -- please fix symbol path for NETBT\n");
  583. return;
  584. }
  585. local_addr = ReadField(pLocalHashTbl);
  586. remote_addr = ReadField(pRemoteHashTbl);
  587. if (_stricmp(args, "local") == 0) {
  588. PRINTF ("Dumping local cache %I64lx", local_addr);
  589. dump_cache (local_addr);
  590. } else if (_stricmp(args, "remote") == 0) {
  591. PRINTF ("Dumping remote cache %I64lx", remote_addr);
  592. dump_cache (remote_addr);
  593. } else {
  594. PRINTF ("Dumping local cache %I64lx", local_addr);
  595. dump_cache (local_addr);
  596. PRINTF ("Dumping remote cache %I64lx", remote_addr);
  597. dump_cache (remote_addr);
  598. }
  599. PRINTF( "---------------- Cache ----------------\n");
  600. return;
  601. }
  602. DECLARE_API (localname)
  603. {
  604. ULONG linkage_offset;
  605. ULONG32 tag;
  606. ULONG64 addr;
  607. if (*args == 0) {
  608. PRINTF ("Usage: localname pointer\n");
  609. return;
  610. }
  611. addr = GetExpression(args);
  612. if (GetFieldValue(addr, "netbt!tNAMEADDR", "Verify", tag)) {
  613. PRINTF ("Error -- please fix symbol path for NETBT\n");
  614. return;
  615. }
  616. if (tag == REMOTE_NAME) {
  617. PRINTF ("%I64x is a remote name. Please use a local name.\n", addr);
  618. return;
  619. }
  620. if (tag == LOCAL_NAME) {
  621. ULONG addr_offset;
  622. /*
  623. * GetFieldValue won't do signextended for 32-bit. Use ReadPtr
  624. */
  625. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"pAddressEle", &addr_offset)) {
  626. PRINTF ("Error -- please fix symbol path for NETBT\n");
  627. return;
  628. }
  629. if (ReadPtr(addr + addr_offset, &addr)) {
  630. PRINTF ("Error -- please fix symbol path for NETBT\n");
  631. return;
  632. }
  633. }
  634. if (GetFieldValue(addr, "netbt!tADDRESSELE", "Verify", tag)) {
  635. PRINTF ("Error -- please fix symbol path for NETBT\n");
  636. return;
  637. }
  638. if (tag != NBT_VERIFY_ADDRESS) {
  639. PRINTF ("%I64x is not a local name. Please use a local name.\n", addr);
  640. return;
  641. }
  642. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"Linkage", &linkage_offset)) {
  643. PRINTF ("Error -- please fix symbol path for NETBT\n");
  644. return;
  645. }
  646. addresses_callback(addr - linkage_offset, NULL);
  647. }
  648. ULONG
  649. dump_field_callback(PFIELD_INFO pField, PVOID context)
  650. {
  651. PRINTF ("%s, %s, %I64lx\n", pField->fName, pField->printName, pField->address);
  652. return 0;
  653. }
  654. DECLARE_API(dump)
  655. {
  656. PRINTF ("dump is no longer supported because 'dt type address' is better\n");
  657. PRINTF ("\tFor example 'dt netbt!tDEVICECONTEXT 0x98765432'\n");
  658. }
  659. /*
  660. * read in a list entry and a ULONG following that list entry.
  661. */
  662. __inline ULONG
  663. read_list_verify(
  664. ULONG64 addr,
  665. PLIST_ENTRY64 List,
  666. ULONG *verify
  667. )
  668. {
  669. static ULONG list_size = 0;
  670. ULONG64 a;
  671. if (list_size == 0) {
  672. list_size = GetTypeSize("LIST_ENTRY");
  673. }
  674. if (InitTypeRead(addr, LIST_ENTRY)) {
  675. return 1;
  676. }
  677. List->Flink = ReadField(Flink);
  678. List->Blink = ReadField(Blink);
  679. if (GetFieldData(addr+list_size, "ULONG", NULL, sizeof(ULONG64), &a)) {
  680. return 1;
  681. }
  682. *verify = (ULONG)a;
  683. return 0;
  684. }
  685. DECLARE_API(verifyll)
  686. {
  687. LIST_ENTRY64 list;
  688. ULONG64 pHead, pCurrentEntry, pNextEntry, pPreviousEntry;
  689. ULONG VerifyRead, VerifyIn = 0;
  690. ULONG Count = 0;
  691. BOOL fVerifyIn = FALSE;
  692. BOOL fListCorrupt = FALSE;
  693. PRINTF ("Verifying Linked list ...\n");
  694. if (!args || !(*args)) {
  695. PRINTF ("Usage: !NetbtKd.VerifyLL <ListHead>\n");
  696. return;
  697. } else {
  698. //
  699. // args = "<pHead> [<Verify>]"
  700. //
  701. LPSTR lpVerify;
  702. while (*args == ' ') {
  703. args++;
  704. }
  705. lpVerify = strpbrk(args, NAME_DELIMITERS);
  706. pHead = GetExpression (args);
  707. if (lpVerify) {
  708. VerifyIn = (ULONG)GetExpression (lpVerify);
  709. fVerifyIn = TRUE;
  710. }
  711. }
  712. PRINTF ("** ListHead@<%I64lx>, fVerifyIn=<%x>, VerifyIn=<%x>:\n\n", pHead, fVerifyIn, VerifyIn);
  713. PRINTF ("Verifying Flinks ...");
  714. // Read in the data for the first FLink in the list!
  715. pPreviousEntry = pHead;
  716. if (READLISTENTRY(pHead, &list)) {
  717. PRINTF ("Failed to read memory 0x%I64lx\n", pHead);
  718. return;
  719. }
  720. pCurrentEntry = list.Flink;
  721. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  722. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  723. return;
  724. }
  725. pNextEntry = list.Flink;
  726. while ((pCurrentEntry != pHead) && (++Count < MAX_LIST_ELEMENTS)) {
  727. if (CheckControlC()) {
  728. break;
  729. }
  730. if ((fVerifyIn) && (VerifyRead != VerifyIn)) {
  731. PRINTF ("Verify FAILURE:\n\t<%d> Elements Read so far\n"
  732. "\tPrevious=<%I64lx>, Current=<%I64lx>, Next=<%I64lx>\n",
  733. Count, pPreviousEntry, pCurrentEntry, pNextEntry);
  734. fListCorrupt = TRUE;
  735. break;
  736. }
  737. pPreviousEntry = pCurrentEntry;
  738. pCurrentEntry = pNextEntry;
  739. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  740. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  741. return;
  742. }
  743. pNextEntry = list.Flink;
  744. }
  745. if (!fListCorrupt) {
  746. PRINTF ("SUCCESS: %s<%d> Elements!\n", (pCurrentEntry==pHead? "":"> "), Count);
  747. }
  748. PRINTF ("Verifying Blinks ...");
  749. Count = 0;
  750. fListCorrupt = FALSE;
  751. // Read in the data for the first BLink in the list!
  752. pPreviousEntry = pHead;
  753. if (READLISTENTRY(pHead, &list)) {
  754. PRINTF ("Failed to read memory 0x%I64lx\n", pHead);
  755. return;
  756. }
  757. pCurrentEntry = list.Blink;
  758. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  759. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  760. return;
  761. }
  762. pNextEntry = list.Blink;
  763. while ((pCurrentEntry != pHead) && (++Count < MAX_LIST_ELEMENTS)) {
  764. if (CheckControlC()) {
  765. break;
  766. }
  767. if ((fVerifyIn) && (VerifyRead != VerifyIn)) {
  768. PRINTF ("Verify FAILURE:\n\t<%d> Elements Read so far\n"
  769. "\tPrevious=<%I64lx>, Current=<%I64lx>, Next=<%I64lx>\n",
  770. Count, pPreviousEntry, pCurrentEntry, pNextEntry);
  771. fListCorrupt = TRUE;
  772. break;
  773. }
  774. pPreviousEntry = pCurrentEntry;
  775. pCurrentEntry = pNextEntry;
  776. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  777. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  778. return;
  779. }
  780. pNextEntry = list.Blink;
  781. }
  782. if (!fListCorrupt) {
  783. PRINTF ("SUCCESS: %s<%d> Elements!\n", (pCurrentEntry==pHead? "":"> "), Count);
  784. }
  785. PRINTF( "---------------- Verify LinkedList ----------------\n");
  786. return;
  787. }
  788. DECLARE_API(sessionhdr)
  789. {
  790. tSESSIONHDR Hdr;
  791. char called_name[34];
  792. char callee_name[34];
  793. ULONG64 addr;
  794. ULONG Size;
  795. int i;
  796. if (!args || !(*args)) {
  797. PRINTF ("Usage: !NetbtKd.sessionhdr hdr\n");
  798. return;
  799. }
  800. addr = GetExpression(args);
  801. if (addr == 0) {
  802. return;
  803. }
  804. ReadMemory(addr, &Hdr, sizeof(Hdr), &Size);
  805. ReadMemory(addr + sizeof(Hdr), called_name, sizeof(called_name), &Size);
  806. ReadMemory(addr + sizeof(Hdr)+sizeof(called_name), callee_name, sizeof(callee_name), &Size);
  807. if (called_name[0] != 32 || callee_name[0] != 32) {
  808. PRINTF ("Error -- invalid called/callee name length called=%d, callee=%d\n",
  809. (unsigned)called_name[0], (unsigned)callee_name[0]);
  810. return;
  811. }
  812. for (i = 0; i < 16; i++) {
  813. called_name[i + 1] = ((called_name[i*2+1] - 'A') << 4) | (called_name[i*2+2] - 'A');
  814. callee_name[i + 1] = ((callee_name[i*2+1] - 'A') << 4) | (callee_name[i*2+2] - 'A');
  815. }
  816. called_name[i + 1] = 0;
  817. callee_name[i + 1] = 0;
  818. PRINTF ("called name=%15.15s<%02x>\n", called_name+1, (unsigned)called_name[16]);
  819. PRINTF ("callee name=%15.15s<%02x>\n", callee_name+1, (unsigned)callee_name[16]);
  820. return;
  821. }
  822. //
  823. // Standard Functions
  824. //
  825. DllInit(
  826. HANDLE hModule,
  827. DWORD dwReason,
  828. DWORD dwReserved
  829. )
  830. {
  831. switch (dwReason) {
  832. case DLL_THREAD_ATTACH:
  833. break;
  834. case DLL_THREAD_DETACH:
  835. break;
  836. case DLL_PROCESS_DETACH:
  837. break;
  838. case DLL_PROCESS_ATTACH:
  839. break;
  840. }
  841. return TRUE;
  842. }
  843. VOID
  844. WinDbgExtensionDllInit(
  845. PWINDBG_EXTENSION_APIS lpExtensionApis,
  846. USHORT MajorVersion,
  847. USHORT MinorVersion
  848. )
  849. {
  850. ExtensionApis = *lpExtensionApis;
  851. SavedMajorVersion = MajorVersion;
  852. SavedMinorVersion = MinorVersion;
  853. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  854. init(0, 0, 0, 0, "");
  855. return;
  856. }
  857. VOID
  858. CheckVersion(VOID)
  859. {
  860. return;
  861. }
  862. LPEXT_API_VERSION
  863. ExtensionApiVersion(
  864. VOID
  865. )
  866. {
  867. return &ApiVersion;
  868. }