Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1082 lines
31 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. "nbtworkitems Dump netbt workitems",
  136. 0
  137. };
  138. BOOL
  139. help(void)
  140. {
  141. int i;
  142. for( i=0; Extensions[i]; i++ )
  143. PRINTF( " %s\n", Extensions[i] );
  144. for( i=0; LibCommands[i]; i++ )
  145. PRINTF( " %s\n", LibCommands[i] );
  146. return TRUE;
  147. }
  148. DECLARE_API(version)
  149. {
  150. #if DBG
  151. PCHAR DebuggerType = "Checked";
  152. #else
  153. PCHAR DebuggerType = "Free";
  154. #endif
  155. PRINTF ( "NETBT: %s extension dll (build %d) debugging %s kernel (build %d)\n",
  156. DebuggerType,
  157. VER_PRODUCTBUILD,
  158. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  159. SavedMinorVersion
  160. );
  161. }
  162. #define NAME_DELIMITER '@'
  163. #define NAME_DELIMITERS "@ "
  164. #define INVALID_INDEX 0xffffffff
  165. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  166. void
  167. dump_device(ULONG64 addr)
  168. {
  169. ULONG linkage_offset = 0;
  170. ULONG tag;
  171. ULONG ip, subnet_mask, assigned_ip, name_server1, name_server2;
  172. UCHAR mac[6];
  173. if (GetFieldOffset("netbt!tDEVICECONTEXT", (LPSTR)"Linkage", &linkage_offset)) {
  174. PRINTF ("Error -- please fix symbol path for NETBT\n");
  175. return;
  176. }
  177. InitTypeRead(addr, netbt!tDEVICECONTEXT);
  178. tag = (ULONG)ReadField(Verify);
  179. if (tag != NBT_VERIFY_DEVCONTEXT && tag != NBT_VERIFY_DEVCONTEXT_DOWN) {
  180. addr -= linkage_offset;
  181. InitTypeRead(addr, netbt!tDEVICECONTEXT);
  182. tag = (ULONG)ReadField(Verify);
  183. if (tag != NBT_VERIFY_DEVCONTEXT && tag != NBT_VERIFY_DEVCONTEXT_DOWN) {
  184. PRINTF ("Tag not found. %I64lx may not be a valid NETBT device\n", addr + linkage_offset);
  185. return;
  186. }
  187. }
  188. PRINTF ("+++++++++++++++ tDEVICECONTEXT @ %I64lx (%s) ++++++++++++++++\n",
  189. addr, (tag == NBT_VERIFY_DEVCONTEXT)? "Active": "Down");
  190. ip = (ULONG)ReadField(IpAddress);
  191. assigned_ip = (ULONG)ReadField(AssignedIpAddress);
  192. subnet_mask = (ULONG)ReadField(SubnetMask);
  193. GetFieldData(addr, "netbt!tDEVICECONTEXT", "MacAddress", 6, mac);
  194. PRINTF (" IP Address: %s\n", inet_addr(ip, NULL));
  195. PRINTF ("IP Interface Flag: %I64lx\n", ReadField(IpInterfaceFlags));
  196. PRINTF (" MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  197. PRINTF (" subnet: %s\n", inet_addr(subnet_mask & ip, NULL));
  198. if (ip != assigned_ip) {
  199. PRINTF (" Assigned Address: %s\n", inet_addr(assigned_ip, NULL));
  200. }
  201. PRINTF (" subnet mask: %s\n", inet_addr(subnet_mask, NULL));
  202. PRINTF ("broadcast address: %s\n", inet_addr((ULONG)ReadField(BroadcastAddress), NULL));
  203. PRINTF (" network mask: %s\n", inet_addr((ULONG)ReadField(NetMask), NULL));
  204. name_server1 = (ULONG)ReadField(lNameServerAddress);
  205. name_server2 = (ULONG)ReadField(lBackupServer);
  206. if (name_server1 == 0) {
  207. PRINTF (" WINS: <not configured>\n");
  208. } else if (name_server2 == 0) {
  209. PRINTF (" WINS: %s\n", inet_addr(name_server1, NULL));
  210. } else {
  211. if (ReadField(SwitchedToBackup)) {
  212. PRINTF (" Primary WINS: %s\n", inet_addr(name_server2, NULL));
  213. PRINTF (" Secondary WINS: %s (in use)\n", inet_addr(name_server1, NULL));
  214. } else {
  215. PRINTF (" Primary WINS: %s (in use)\n", inet_addr(name_server1, NULL));
  216. PRINTF (" Secondary WINS: %s\n", inet_addr(name_server2, NULL));
  217. }
  218. }
  219. if (ReadField(WinsIsDown)) {
  220. PRINTF ("************* WINS(s) ARE DOWN ***************\n");
  221. }
  222. PRINTF (" pFileObject: %I64lx (type netbt!tFILE_OBJECTS)\n", ReadField(pFileObjects));
  223. PRINTF ("TCP Session: HANDLE=%I64lx DeviceObject=%I64lx FileObject=%I64lx\n",
  224. ReadField(hSession), ReadField(pSessionDeviceObject), ReadField(pSessionFileObject));
  225. PRINTF ("TCP Control: HANDLE=%I64lx DeviceObject=%I64lx FileObject=%I64lx\n",
  226. ReadField(hControl), ReadField(pControlDeviceObject), ReadField(pControlFileObject));
  227. PRINTF ("\n");
  228. }
  229. /*++
  230. Dump a NETBT device
  231. --*/
  232. DECLARE_API (dev)
  233. {
  234. if (*args == 0) {
  235. return;
  236. }
  237. dump_device(GetExpression(args));
  238. }
  239. /*++
  240. Dump all NETBT devices
  241. --*/
  242. DECLARE_API (devices)
  243. {
  244. ULONG64 NbtSmbDevice;
  245. ULONG Offset;
  246. USHORT AdapterCounter;
  247. int num;
  248. GetFieldValue(ConfigPtr, "netbt!tNBTCONFIG", "AdapterCount", AdapterCounter);
  249. /*
  250. * SMB device
  251. */
  252. NbtSmbDevice = GetExpression("netbt!pNbtSmbDevice");
  253. ReadPtr(NbtSmbDevice, &NbtSmbDevice);
  254. PRINTF( "Dumping SMB device\n");
  255. dump_device(NbtSmbDevice);
  256. /*
  257. * dump device list
  258. */
  259. if (GetFieldOffset("netbt!tNBTCONFIG", (LPSTR)"DeviceContexts", &Offset)) {
  260. PRINTF ("Error -- please fix symbol path for NETBT\n");
  261. return;
  262. }
  263. num = ListForEach(ConfigPtr + Offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)dump_device);
  264. PRINTF ("Total devices = %d (include SMB device)\n", num + 1);
  265. /*
  266. * Check consistency
  267. */
  268. if (num != AdapterCounter) {
  269. PRINTF ("Inconsistent!!! Number of devices = %d in NbtConfig.AdapterCount\n", AdapterCounter);
  270. }
  271. }
  272. /*
  273. * call back function for dumping a list of listening request
  274. */
  275. BOOL
  276. listen_callback(ULONG64 addr, PVOID pContext)
  277. {
  278. ULONG irp_offset;
  279. ULONG linkage_offset;
  280. ULONG64 irp_addr;
  281. if (GetFieldOffset("netbt!tLISTENREQUESTS", (LPSTR)"pIrp", &irp_offset)) {
  282. PRINTF ("Error -- please fix symbol path for NETBT\n");
  283. return FALSE;
  284. }
  285. if (GetFieldOffset("netbt!tLISTENREQUESTS", (LPSTR)"Linkage", &linkage_offset)) {
  286. PRINTF ("Error -- please fix symbol path for NETBT\n");
  287. return FALSE;
  288. }
  289. addr -= linkage_offset;
  290. if (ReadPtr(addr+irp_offset, &irp_addr)) {
  291. PRINTF ("Error -- please fix symbol path for NETBT\n");
  292. return FALSE;
  293. }
  294. PRINTF ("\t\t ** pListen@<%I64lx> ==> pIrp = %I64lx\n", addr, irp_addr);
  295. return TRUE;
  296. }
  297. /*
  298. * call back function for dumping a list of connection element
  299. */
  300. BOOL
  301. connect_callback(ULONG64 addr, PVOID pContext)
  302. {
  303. ULONG linkage_offset;
  304. UCHAR name[NETBIOS_NAME_SIZE];
  305. if (GetFieldOffset("netbt!tCONNECTELE", (LPSTR)"Linkage", &linkage_offset)) {
  306. PRINTF ("Error -- please fix symbol path for NETBT\n");
  307. return FALSE;
  308. }
  309. addr -= linkage_offset;
  310. if (GetFieldData(addr, "netbt!tCONNECTELE", "RemoteName", NETBIOS_NAME_SIZE, name)) {
  311. PRINTF ("Error -- please fix symbol path for NETBT\n");
  312. return FALSE;
  313. }
  314. PRINTF ("\t\t ** Connection@<%I64lx> ==> <%-15.15s:%x>\n", addr, name, name[15]&0xff);
  315. return TRUE;
  316. }
  317. /*
  318. * call back function for dumping a list of client element
  319. */
  320. BOOL
  321. client_callback(ULONG64 addr, PVOID pContext)
  322. {
  323. ULONG connect_offset;
  324. ULONG listen_offset;
  325. ULONG active_connect_offset;
  326. ULONG linkage_offset, tag;
  327. UCHAR name[NETBIOS_NAME_SIZE];
  328. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"Linkage", &linkage_offset)) {
  329. PRINTF ("Error -- please fix symbol path for NETBT\n");
  330. return FALSE;
  331. }
  332. addr -= linkage_offset;
  333. if (InitTypeRead(addr, netbt!tCLIENTELE)) {
  334. PRINTF ("Error -- please fix symbol path for NETBT\n");
  335. return FALSE;
  336. }
  337. tag = (ULONG)ReadField(Verify);
  338. if (tag == NBT_VERIFY_CLIENT) {
  339. PRINTF ("\tActive ");
  340. } else if (tag == NBT_VERIFY_CLIENT_DOWN) {
  341. PRINTF ("\tClosed ");
  342. } else {
  343. PRINTF ("\tClient @ %I64lx: bad client tag: %lx\n", addr, tag);
  344. return FALSE;
  345. }
  346. if (GetFieldData(addr, "netbt!tCLIENTELE", "EndpointName", NETBIOS_NAME_SIZE, name)) {
  347. PRINTF ("Error -- please fix symbol path for NETBT\n");
  348. return FALSE;
  349. }
  350. PRINTF ("Client@<%I64lx> ==> pDevice = %I64lx\tEndpoint=<%-15.15s:%x>\n",
  351. addr, ReadField(pDeviceContext), name, name[15]);
  352. /*
  353. * dump the connection associated with the client element
  354. */
  355. PRINTF ("\t\t(ConnectHead):\n");
  356. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ConnectHead", &connect_offset)) {
  357. PRINTF ("Error -- please fix symbol path for NETBT\n");
  358. return FALSE;
  359. }
  360. ListForEach(addr + connect_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)connect_callback);
  361. PRINTF ("\t\t(ConnectActive)\n");
  362. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ConnectActive", &active_connect_offset)) {
  363. PRINTF ("Error -- please fix symbol path for NETBT\n");
  364. return FALSE;
  365. }
  366. ListForEach(addr + active_connect_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)connect_callback);
  367. PRINTF ("\t\t(ListenHead):\n");
  368. if (GetFieldOffset("netbt!tCLIENTELE", (LPSTR)"ListenHead", &listen_offset)) {
  369. PRINTF ("Error -- please fix symbol path for NETBT\n");
  370. return FALSE;
  371. }
  372. ListForEach(addr + listen_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)listen_callback);
  373. PRINTF ("\n");
  374. return TRUE;
  375. }
  376. /*
  377. * call back function for dumping a list of address element
  378. */
  379. BOOL
  380. addresses_callback(ULONG64 addr, PVOID pContext)
  381. {
  382. UCHAR name[NETBIOS_NAME_SIZE];
  383. ULONG64 NameAddr;
  384. ULONG tag, linkage_offset, client_offset;
  385. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"Linkage", &linkage_offset)) {
  386. PRINTF ("Error -- please fix symbol path for NETBT: %d of %s\n", __LINE__, __FILE__);
  387. return FALSE;
  388. }
  389. addr -= linkage_offset;
  390. if (InitTypeRead(addr, netbt!tADDRESSELE)) {
  391. PRINTF ("Error -- please fix symbol path for NETBT: %I64lx\n", addr);
  392. return FALSE;
  393. }
  394. tag = (ULONG)ReadField(Verify);
  395. /*
  396. * Check tag
  397. */
  398. if (tag != NBT_VERIFY_ADDRESS) {
  399. PRINTF ("ERROR: incorrect tag <%4.4s>. %lx is properly not a address element\n", tag, addr);
  400. return FALSE;
  401. }
  402. /*
  403. * Print out the address element
  404. */
  405. NameAddr = ReadField(pNameAddr);
  406. if (GetFieldData(NameAddr, "netbt!tNAMEADDR", "Name", NETBIOS_NAME_SIZE, name)) {
  407. PRINTF ("Error -- please fix symbol path for NETBT: pNameAddr=%I64lx\n", NameAddr);
  408. return FALSE;
  409. }
  410. PRINTF ("Address@<%I64lx> ==> <%-15.15s:%x>\n", addr, name, name[15]);
  411. /*
  412. * dump the client element associated with the address element
  413. */
  414. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"ClientHead", &client_offset)) {
  415. PRINTF ("Error -- please fix symbol path for NETBT: %I64lx\n", addr);
  416. return FALSE;
  417. }
  418. ListForEach(addr + client_offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)client_callback);
  419. return TRUE;
  420. }
  421. DECLARE_API(connections)
  422. {
  423. ULONG Offset;
  424. if (GetFieldOffset("netbt!tNBTCONFIG", (LPSTR)"AddressHead", &Offset)) {
  425. PRINTF ("Error -- please fix symbol path for NETBT\n");
  426. return;
  427. }
  428. PRINTF ("Dumping information on all NetBT conections ...\n");
  429. ListForEach(ConfigPtr + Offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)addresses_callback);
  430. PRINTF( "---------------- End of Connections ----------------\n");
  431. }
  432. char* inet_addr(ULONG ip, char* addr)
  433. {
  434. static char my_addr[16];
  435. if (addr == NULL) {
  436. addr = my_addr;
  437. }
  438. sprintf (addr, "%d.%d.%d.%d",
  439. (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
  440. return addr;
  441. }
  442. WCHAR*
  443. GetUnicodeString(ULONG64 addr)
  444. {
  445. USHORT length;
  446. ULONG readed_bytes;
  447. ULONG64 buffer = 0;
  448. WCHAR *p;
  449. InitTypeRead(addr, netbt!UNICODE_STRING);
  450. length = (USHORT)ReadField(Length);
  451. buffer = ReadField(Buffer);
  452. if (buffer == 0 || length == 0) {
  453. return NULL;
  454. }
  455. p = (WCHAR*)LocalAlloc(LMEM_FIXED, length + sizeof(WCHAR));
  456. if (p == NULL) {
  457. return NULL;
  458. }
  459. ReadMemory(buffer, (PVOID)p, length, &readed_bytes);
  460. if ((USHORT)readed_bytes != length) {
  461. LocalFree(p);
  462. return NULL;
  463. }
  464. p[length/sizeof(WCHAR)] = L'\0';
  465. return p;
  466. }
  467. /*
  468. * call back function for dumping a list of cache entries
  469. */
  470. BOOL
  471. cache_callback(ULONG64 addr, const int *bkt)
  472. {
  473. static ULONG addr_offset = (ULONG)(-1);
  474. static ULONG fqdn_offset = (ULONG)(-1);
  475. ULONG Verify;
  476. UCHAR name[NETBIOS_NAME_SIZE];
  477. ULONG ip, refcnt, state, ttl;
  478. WCHAR *fqdn = NULL;
  479. if (addr_offset == (ULONG)(-1)) {
  480. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"Linkage", &addr_offset)) {
  481. PRINTF ("Error -- please fix symbol path for NETBT\n");
  482. addr_offset = (ULONG)(-1);
  483. return FALSE;
  484. }
  485. }
  486. if (fqdn_offset == (ULONG)(-1)) {
  487. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"FQDN", &fqdn_offset)) {
  488. fqdn_offset = (ULONG)(-1);
  489. }
  490. }
  491. addr -= addr_offset;
  492. if (InitTypeRead(addr, netbt!tNAMEADDR)) {
  493. PRINTF ("Error -- please fix symbol path for NETBT\n");
  494. return FALSE;
  495. }
  496. Verify = (ULONG)ReadField(Verify);
  497. if (Verify != LOCAL_NAME && Verify != REMOTE_NAME) {
  498. PRINTF ("ERROR: bad name cache entry @ %I64x tag %lx!\n", addr, Verify);
  499. return FALSE;
  500. }
  501. ip = (ULONG)ReadField(IpAddress);
  502. refcnt = (ULONG)ReadField(RefCount);
  503. state = (ULONG)ReadField(NameTypeState);
  504. ttl = (ULONG)ReadField(Ttl);
  505. if (GetFieldData(addr, "netbt!tNAMEADDR", "Name", NETBIOS_NAME_SIZE, name)) {
  506. PRINTF ("Error -- please fix symbol path for NETBT\n");
  507. return FALSE;
  508. }
  509. if (fqdn_offset != (ULONG)(-1)) {
  510. fqdn = GetUnicodeString(addr + fqdn_offset);
  511. }
  512. PRINTF ("[%d]\t<%16.16I64lx> => <%-15.15s:%2x> | %-15.15s | %d | %8x | %9d\n",
  513. *bkt, addr, name, name[15], inet_addr(ip, NULL), refcnt, state, ttl);
  514. if (fqdn != NULL) {
  515. PRINTF("\t\t%ws\n", fqdn);
  516. LocalFree(fqdn);
  517. fqdn = NULL;
  518. }
  519. PRINTF("\t\tName State:");
  520. if (state & NAMETYPE_QUICK) {
  521. PRINTF(" QUICK");
  522. }
  523. if (state & NAMETYPE_UNIQUE) {
  524. PRINTF(" UNIQUE");
  525. }
  526. if (state & NAMETYPE_GROUP) {
  527. PRINTF(" GROUP");
  528. }
  529. if (state & NAMETYPE_INET_GROUP) {
  530. PRINTF(" INET_GROUP");
  531. }
  532. if (state & STATE_RESOLVED) {
  533. PRINTF(" RESOLVED");
  534. }
  535. if (state & STATE_RELEASED) {
  536. PRINTF(" RELEASED");
  537. }
  538. if (state & STATE_CONFLICT) {
  539. PRINTF(" CONFLICT");
  540. }
  541. if (state & STATE_RESOLVING) {
  542. PRINTF(" RESOLVING");
  543. }
  544. if (state & REFRESH_FAILED) {
  545. PRINTF(" REFRESH_FAILED");
  546. }
  547. if (state & PRELOADED) {
  548. PRINTF(" PRELOADED");
  549. }
  550. PRINTF("\n");
  551. return TRUE;
  552. }
  553. void
  554. dump_cache(ULONG64 addr)
  555. {
  556. LONG bucket_number;
  557. int i;
  558. static ULONG buckets_offset = (ULONG)(-1);
  559. static ULONG sizeof_list;
  560. if (buckets_offset == (ULONG)(-1)) {
  561. if (GetFieldOffset("netbt!tHASHTABLE", (LPSTR)"Bucket", &buckets_offset)) {
  562. PRINTF ("\nError -- please fix symbol path for NETBT\n");
  563. return;
  564. }
  565. sizeof_list = GetTypeSize ("LIST_ENTRY");
  566. }
  567. if (InitTypeRead(addr, netbt!tHASHTABLE)) {
  568. PRINTF ("\nError -- please fix symbol path for NETBT\n");
  569. return;
  570. }
  571. bucket_number = (ULONG) ReadField(lNumBuckets);
  572. PRINTF (" %d buckets\n", bucket_number);
  573. PRINTF ("[Bkt#]\t< Address > => <Name > | IpAddr | RefC | State | Ttl\n");
  574. for (i=0; i < bucket_number; i++) {
  575. ListForEach(addr + buckets_offset + i * sizeof_list, -1, &i, (LIST_FOR_EACH_CALLBACK)cache_callback);
  576. }
  577. PRINTF ("-----------------------------------------------------------------------------------\n");
  578. }
  579. DECLARE_API (cache)
  580. {
  581. ULONG64 local_addr, remote_addr;
  582. if (InitTypeRead(ConfigPtr, netbt!tNBTCONFIG)) {
  583. PRINTF ("Error -- please fix symbol path for NETBT\n");
  584. return;
  585. }
  586. local_addr = ReadField(pLocalHashTbl);
  587. remote_addr = ReadField(pRemoteHashTbl);
  588. if (_stricmp(args, "local") == 0) {
  589. PRINTF ("Dumping local cache %I64lx", local_addr);
  590. dump_cache (local_addr);
  591. } else if (_stricmp(args, "remote") == 0) {
  592. PRINTF ("Dumping remote cache %I64lx", remote_addr);
  593. dump_cache (remote_addr);
  594. } else {
  595. PRINTF ("Dumping local cache %I64lx", local_addr);
  596. dump_cache (local_addr);
  597. PRINTF ("Dumping remote cache %I64lx", remote_addr);
  598. dump_cache (remote_addr);
  599. }
  600. PRINTF( "---------------- Cache ----------------\n");
  601. return;
  602. }
  603. DECLARE_API (localname)
  604. {
  605. ULONG linkage_offset;
  606. ULONG32 tag;
  607. ULONG64 addr;
  608. if (*args == 0) {
  609. PRINTF ("Usage: localname pointer\n");
  610. return;
  611. }
  612. addr = GetExpression(args);
  613. if (GetFieldValue(addr, "netbt!tNAMEADDR", "Verify", tag)) {
  614. PRINTF ("Error -- please fix symbol path for NETBT\n");
  615. return;
  616. }
  617. if (tag == REMOTE_NAME) {
  618. PRINTF ("%I64x is a remote name. Please use a local name.\n", addr);
  619. return;
  620. }
  621. if (tag == LOCAL_NAME) {
  622. ULONG addr_offset;
  623. /*
  624. * GetFieldValue won't do signextended for 32-bit. Use ReadPtr
  625. */
  626. if (GetFieldOffset("netbt!tNAMEADDR", (LPSTR)"pAddressEle", &addr_offset)) {
  627. PRINTF ("Error -- please fix symbol path for NETBT\n");
  628. return;
  629. }
  630. if (ReadPtr(addr + addr_offset, &addr)) {
  631. PRINTF ("Error -- please fix symbol path for NETBT\n");
  632. return;
  633. }
  634. }
  635. if (GetFieldValue(addr, "netbt!tADDRESSELE", "Verify", tag)) {
  636. PRINTF ("Error -- please fix symbol path for NETBT\n");
  637. return;
  638. }
  639. if (tag != NBT_VERIFY_ADDRESS) {
  640. PRINTF ("%I64x is not a local name. Please use a local name.\n", addr);
  641. return;
  642. }
  643. if (GetFieldOffset("netbt!tADDRESSELE", (LPSTR)"Linkage", &linkage_offset)) {
  644. PRINTF ("Error -- please fix symbol path for NETBT\n");
  645. return;
  646. }
  647. addresses_callback(addr - linkage_offset, NULL);
  648. }
  649. ULONG
  650. dump_field_callback(PFIELD_INFO pField, PVOID context)
  651. {
  652. PRINTF ("%s, %s, %I64lx\n", pField->fName, pField->printName, pField->address);
  653. return 0;
  654. }
  655. DECLARE_API(dump)
  656. {
  657. PRINTF ("dump is no longer supported because 'dt type address' is better\n");
  658. PRINTF ("\tFor example 'dt netbt!tDEVICECONTEXT 0x98765432'\n");
  659. }
  660. /*
  661. * read in a list entry and a ULONG following that list entry.
  662. */
  663. __inline ULONG
  664. read_list_verify(
  665. ULONG64 addr,
  666. PLIST_ENTRY64 List,
  667. ULONG *verify
  668. )
  669. {
  670. static ULONG list_size = 0;
  671. ULONG64 a;
  672. if (list_size == 0) {
  673. list_size = GetTypeSize("LIST_ENTRY");
  674. }
  675. if (InitTypeRead(addr, LIST_ENTRY)) {
  676. return 1;
  677. }
  678. List->Flink = ReadField(Flink);
  679. List->Blink = ReadField(Blink);
  680. if (GetFieldData(addr+list_size, "ULONG", NULL, sizeof(ULONG64), &a)) {
  681. return 1;
  682. }
  683. *verify = (ULONG)a;
  684. return 0;
  685. }
  686. DECLARE_API(verifyll)
  687. {
  688. LIST_ENTRY64 list;
  689. ULONG64 pHead, pCurrentEntry, pNextEntry, pPreviousEntry;
  690. ULONG VerifyRead, VerifyIn = 0;
  691. ULONG Count = 0;
  692. BOOL fVerifyIn = FALSE;
  693. BOOL fListCorrupt = FALSE;
  694. PRINTF ("Verifying Linked list ...\n");
  695. if (!args || !(*args)) {
  696. PRINTF ("Usage: !NetbtKd.VerifyLL <ListHead>\n");
  697. return;
  698. } else {
  699. //
  700. // args = "<pHead> [<Verify>]"
  701. //
  702. LPSTR lpVerify;
  703. while (*args == ' ') {
  704. args++;
  705. }
  706. lpVerify = strpbrk(args, NAME_DELIMITERS);
  707. pHead = GetExpression (args);
  708. if (lpVerify) {
  709. VerifyIn = (ULONG)GetExpression (lpVerify);
  710. fVerifyIn = TRUE;
  711. }
  712. }
  713. PRINTF ("** ListHead@<%I64lx>, fVerifyIn=<%x>, VerifyIn=<%x>:\n\n", pHead, fVerifyIn, VerifyIn);
  714. PRINTF ("Verifying Flinks ...");
  715. // Read in the data for the first FLink in the list!
  716. pPreviousEntry = pHead;
  717. if (READLISTENTRY(pHead, &list)) {
  718. PRINTF ("Failed to read memory 0x%I64lx\n", pHead);
  719. return;
  720. }
  721. pCurrentEntry = list.Flink;
  722. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  723. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  724. return;
  725. }
  726. pNextEntry = list.Flink;
  727. while ((pCurrentEntry != pHead) && (++Count < MAX_LIST_ELEMENTS)) {
  728. if (CheckControlC()) {
  729. break;
  730. }
  731. if ((fVerifyIn) && (VerifyRead != VerifyIn)) {
  732. PRINTF ("Verify FAILURE:\n\t<%d> Elements Read so far\n"
  733. "\tPrevious=<%I64lx>, Current=<%I64lx>, Next=<%I64lx>\n",
  734. Count, pPreviousEntry, pCurrentEntry, pNextEntry);
  735. fListCorrupt = TRUE;
  736. break;
  737. }
  738. pPreviousEntry = pCurrentEntry;
  739. pCurrentEntry = pNextEntry;
  740. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  741. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  742. return;
  743. }
  744. pNextEntry = list.Flink;
  745. }
  746. if (!fListCorrupt) {
  747. PRINTF ("SUCCESS: %s<%d> Elements!\n", (pCurrentEntry==pHead? "":"> "), Count);
  748. }
  749. PRINTF ("Verifying Blinks ...");
  750. Count = 0;
  751. fListCorrupt = FALSE;
  752. // Read in the data for the first BLink in the list!
  753. pPreviousEntry = pHead;
  754. if (READLISTENTRY(pHead, &list)) {
  755. PRINTF ("Failed to read memory 0x%I64lx\n", pHead);
  756. return;
  757. }
  758. pCurrentEntry = list.Blink;
  759. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  760. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  761. return;
  762. }
  763. pNextEntry = list.Blink;
  764. while ((pCurrentEntry != pHead) && (++Count < MAX_LIST_ELEMENTS)) {
  765. if (CheckControlC()) {
  766. break;
  767. }
  768. if ((fVerifyIn) && (VerifyRead != VerifyIn)) {
  769. PRINTF ("Verify FAILURE:\n\t<%d> Elements Read so far\n"
  770. "\tPrevious=<%I64lx>, Current=<%I64lx>, Next=<%I64lx>\n",
  771. Count, pPreviousEntry, pCurrentEntry, pNextEntry);
  772. fListCorrupt = TRUE;
  773. break;
  774. }
  775. pPreviousEntry = pCurrentEntry;
  776. pCurrentEntry = pNextEntry;
  777. if (read_list_verify(pCurrentEntry, &list, &VerifyRead)) {
  778. PRINTF ("Failed to read memory 0x%I64lx\n", pCurrentEntry);
  779. return;
  780. }
  781. pNextEntry = list.Blink;
  782. }
  783. if (!fListCorrupt) {
  784. PRINTF ("SUCCESS: %s<%d> Elements!\n", (pCurrentEntry==pHead? "":"> "), Count);
  785. }
  786. PRINTF( "---------------- Verify LinkedList ----------------\n");
  787. return;
  788. }
  789. DECLARE_API(sessionhdr)
  790. {
  791. tSESSIONHDR Hdr;
  792. char called_name[34];
  793. char callee_name[34];
  794. ULONG64 addr;
  795. ULONG Size;
  796. int i;
  797. if (!args || !(*args)) {
  798. PRINTF ("Usage: !NetbtKd.sessionhdr hdr\n");
  799. return;
  800. }
  801. addr = GetExpression(args);
  802. if (addr == 0) {
  803. return;
  804. }
  805. ReadMemory(addr, &Hdr, sizeof(Hdr), &Size);
  806. ReadMemory(addr + sizeof(Hdr), called_name, sizeof(called_name), &Size);
  807. ReadMemory(addr + sizeof(Hdr)+sizeof(called_name), callee_name, sizeof(callee_name), &Size);
  808. if (called_name[0] != 32 || callee_name[0] != 32) {
  809. PRINTF ("Error -- invalid called/callee name length called=%d, callee=%d\n",
  810. (unsigned)called_name[0], (unsigned)callee_name[0]);
  811. return;
  812. }
  813. for (i = 0; i < 16; i++) {
  814. called_name[i + 1] = ((called_name[i*2+1] - 'A') << 4) | (called_name[i*2+2] - 'A');
  815. callee_name[i + 1] = ((callee_name[i*2+1] - 'A') << 4) | (callee_name[i*2+2] - 'A');
  816. }
  817. called_name[i + 1] = 0;
  818. callee_name[i + 1] = 0;
  819. PRINTF ("called name=%15.15s<%02x>\n", called_name+1, (unsigned)called_name[16]);
  820. PRINTF ("callee name=%15.15s<%02x>\n", callee_name+1, (unsigned)callee_name[16]);
  821. return;
  822. }
  823. /*
  824. * call back function for dumping a list of workitem entries
  825. */
  826. BOOL
  827. workitem_callback(ULONG64 addr, const int *bkt)
  828. {
  829. static ULONG WorkerRtn_offset = (ULONG)(-1);
  830. static ULONG addr_offset = (ULONG)(-1);
  831. ULONG64 WorkerRoutine = 0;
  832. ULONG64 pTracker = 0;
  833. ULONG64 pDeviceContext = 0;
  834. ULONG64 ClientCompletion = 0;
  835. ULONG64 ClientContext = 0;
  836. UCHAR ucSymbols[128];
  837. ULONG64 uDisplacement = 0;
  838. if (addr_offset == (ULONG)(-1)) {
  839. if (GetFieldOffset("netbt!NBT_WORK_ITEM_CONTEXT", (LPSTR)"Linkage", &addr_offset)) {
  840. PRINTF ("Error -- please fix symbol path for NETBT\n");
  841. addr_offset = (ULONG)(-1);
  842. return FALSE;
  843. }
  844. }
  845. if (WorkerRtn_offset == (ULONG)(-1)) {
  846. if (GetFieldOffset("netbt!NBT_WORK_ITEM_CONTEXT", (LPSTR)"WorkerRoutine", &WorkerRtn_offset)) {
  847. WorkerRtn_offset = (ULONG)(-1);
  848. return FALSE;
  849. }
  850. }
  851. addr -= addr_offset;
  852. if (InitTypeRead(addr, netbt!NBT_WORK_ITEM_CONTEXT)) {
  853. PRINTF ("Error -- please fix symbol path for NETBT\n");
  854. return FALSE;
  855. }
  856. WorkerRoutine = ReadField(WorkerRoutine);
  857. ClientCompletion = ReadField(ClientCompletion);
  858. ClientContext = ReadField(pClientContext);
  859. pTracker = ReadField(pTracker);
  860. pDeviceContext = ReadField(pDeviceContext);
  861. if (0 == WorkerRoutine) {
  862. strcpy(ucSymbols, "null");
  863. } else {
  864. GetSymbol(WorkerRoutine, ucSymbols, &uDisplacement);
  865. }
  866. PRINTF ("%16.16I64lx : %s", addr, ucSymbols);
  867. if (pTracker) {
  868. PRINTF(" pTracker= %16.16I64lx", pTracker);
  869. }
  870. if (pDeviceContext) {
  871. PRINTF(" pDeviceContext= %16.16I64lx", pDeviceContext);
  872. }
  873. if (0 != ClientCompletion) {
  874. GetSymbol(WorkerRoutine, ucSymbols, &uDisplacement);
  875. PRINTF (" pClientCompletion= %s", ucSymbols);
  876. }
  877. if (0 != ClientContext) {
  878. PRINTF (" ClientContext= %16.16I64lx", ClientContext);
  879. }
  880. PRINTF("\n");
  881. return TRUE;
  882. }
  883. DECLARE_API(nbtworkitems)
  884. {
  885. ULONG Offset = 0;
  886. if (GetFieldOffset("netbt!tNBTCONFIG", (LPSTR)"WorkerQList", &Offset)) {
  887. PRINTF ("Error -- please fix symbol path for NETBT\n");
  888. return;
  889. }
  890. ListForEach(ConfigPtr + Offset, -1, NULL, (LIST_FOR_EACH_CALLBACK)workitem_callback);
  891. }
  892. //
  893. // Standard Functions
  894. //
  895. DllInit(
  896. HANDLE hModule,
  897. DWORD dwReason,
  898. DWORD dwReserved
  899. )
  900. {
  901. switch (dwReason) {
  902. case DLL_THREAD_ATTACH:
  903. break;
  904. case DLL_THREAD_DETACH:
  905. break;
  906. case DLL_PROCESS_DETACH:
  907. break;
  908. case DLL_PROCESS_ATTACH:
  909. break;
  910. }
  911. return TRUE;
  912. }
  913. VOID
  914. WinDbgExtensionDllInit(
  915. PWINDBG_EXTENSION_APIS lpExtensionApis,
  916. USHORT MajorVersion,
  917. USHORT MinorVersion
  918. )
  919. {
  920. ExtensionApis = *lpExtensionApis;
  921. SavedMajorVersion = MajorVersion;
  922. SavedMinorVersion = MinorVersion;
  923. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  924. init(0, 0, 0, 0, "");
  925. return;
  926. }
  927. VOID
  928. CheckVersion(VOID)
  929. {
  930. return;
  931. }
  932. LPEXT_API_VERSION
  933. ExtensionApiVersion(
  934. VOID
  935. )
  936. {
  937. return &ApiVersion;
  938. }