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.

412 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. kdextlib.c
  5. Abstract:
  6. Library routines for dumping data structures given a meta level descrioption
  7. Author:
  8. Balan Sethu Raman (SethuR) 11-May-1994
  9. Notes:
  10. The implementation tends to avoid memory allocation and deallocation as much as possible.
  11. Therefore We have choosen an arbitrary length as the default buffer size. A mechanism will
  12. be provided to modify this buffer length through the debugger extension commands.
  13. Revision History:
  14. 11-Nov-1994 SethuR Created
  15. --*/
  16. #include <ntos.h>
  17. #include <nturtl.h>
  18. #include "ntverp.h"
  19. #include <windows.h>
  20. #include <wdbgexts.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <kdextlib.h>
  25. BOOL
  26. kdextAtoi(
  27. LPSTR lpArg,
  28. int *pRet
  29. );
  30. int
  31. kdextStrlen(
  32. LPSTR lpsz
  33. );
  34. int
  35. kdextStrnicmp(
  36. LPSTR lpsz1,
  37. LPSTR lpsz2,
  38. int cLen
  39. );
  40. #define PRINTF dprintf
  41. PWINDBG_OUTPUT_ROUTINE lpOutputRoutine;
  42. PWINDBG_GET_EXPRESSION32 lpGetExpressionRoutine;
  43. PWINDBG_GET_SYMBOL32 lpGetSymbolRoutine;
  44. PWINDBG_READ_PROCESS_MEMORY_ROUTINE lpReadMemoryRoutine;
  45. #define NL 1
  46. #define NONL 0
  47. #define DEFAULT_UNICODE_DATA_LENGTH 512
  48. USHORT s_UnicodeStringDataLength = DEFAULT_UNICODE_DATA_LENGTH;
  49. WCHAR s_UnicodeStringData[DEFAULT_UNICODE_DATA_LENGTH];
  50. WCHAR *s_pUnicodeStringData = s_UnicodeStringData;
  51. #define DEFAULT_ANSI_DATA_LENGTH 512
  52. USHORT s_AnsiStringDataLength = DEFAULT_ANSI_DATA_LENGTH;
  53. CHAR s_AnsiStringData[DEFAULT_ANSI_DATA_LENGTH];
  54. CHAR *s_pAnsiStringData = s_AnsiStringData;
  55. //
  56. // No. of columns used to display struct fields;
  57. //
  58. ULONG s_MaxNoOfColumns = 3;
  59. ULONG s_NoOfColumns = 1;
  60. /*
  61. * Fetches the data at the given address
  62. */
  63. BOOLEAN
  64. GetData( ULONG_PTR dwAddress, PVOID ptr, ULONG size)
  65. {
  66. BOOL b;
  67. ULONG BytesRead;
  68. b = (lpReadMemoryRoutine)(dwAddress, ptr, size, &BytesRead );
  69. if (!b || BytesRead != size ) {
  70. return FALSE;
  71. }
  72. return TRUE;
  73. }
  74. /*
  75. * Fetch the null terminated ASCII string at dwAddress into buf
  76. */
  77. BOOL
  78. GetStringW( DWORD dwAddress, LPWSTR buf )
  79. {
  80. do {
  81. if( !GetData( dwAddress,buf, sizeof(WCHAR)) )
  82. return FALSE;
  83. dwAddress += sizeof(WCHAR);
  84. buf++;
  85. } while( *buf != '\0' );
  86. return TRUE;
  87. }
  88. /*
  89. * Displays a byte in hexadecimal
  90. */
  91. VOID
  92. PrintHexChar( UCHAR c )
  93. {
  94. PRINTF( "%c%c", "0123456789abcdef"[ (c>>4)&7 ], "0123456789abcdef"[ c&7 ] );
  95. }
  96. /*
  97. * Displays a buffer of data in hexadecimal
  98. */
  99. VOID
  100. PrintHexBuf( PUCHAR buf, ULONG cbuf )
  101. {
  102. while( cbuf-- ) {
  103. PrintHexChar( *buf++ );
  104. PRINTF( " " );
  105. }
  106. }
  107. /*
  108. * Displays a unicode string
  109. */
  110. BOOL
  111. PrintStringW(LPSTR msg, PUNICODE_STRING puStr, BOOL nl )
  112. {
  113. UNICODE_STRING UnicodeString;
  114. BOOLEAN b;
  115. if( msg )
  116. PRINTF( msg );
  117. if( puStr->Length == 0 ) {
  118. if( nl )
  119. PRINTF( "\n" );
  120. return TRUE;
  121. }
  122. UnicodeString.Buffer = s_pUnicodeStringData;
  123. UnicodeString.MaximumLength = s_UnicodeStringDataLength;
  124. UnicodeString.Length = (puStr->Length > s_UnicodeStringDataLength)
  125. ? s_UnicodeStringDataLength
  126. : puStr->Length;
  127. b = GetData((ULONG_PTR)puStr->Buffer, UnicodeString.Buffer, (ULONG) UnicodeString.Length);
  128. if (b) {
  129. PRINTF("%wZ%s", &UnicodeString, nl ? "\n" : "" );
  130. }
  131. return b;
  132. }
  133. /*
  134. * Displays a ANSI string
  135. */
  136. BOOL
  137. PrintStringA(LPSTR msg, PANSI_STRING pStr, BOOL nl )
  138. {
  139. ANSI_STRING AnsiString;
  140. BOOL b;
  141. if( msg )
  142. PRINTF( msg );
  143. if( pStr->Length == 0 ) {
  144. if( nl )
  145. PRINTF( "\n" );
  146. return TRUE;
  147. }
  148. AnsiString.Buffer = s_pAnsiStringData;
  149. AnsiString.MaximumLength = s_AnsiStringDataLength;
  150. AnsiString.Length = (pStr->Length > (s_AnsiStringDataLength - 1))
  151. ? (s_AnsiStringDataLength - 1)
  152. : pStr->Length;
  153. b = (lpReadMemoryRoutine)(
  154. (ULONG_PTR)pStr->Buffer,
  155. AnsiString.Buffer,
  156. AnsiString.Length,
  157. NULL);
  158. if (b) {
  159. AnsiString.Buffer[ AnsiString.Length ] = '\0';
  160. PRINTF("%s%s", AnsiString.Buffer, nl ? "\n" : "" );
  161. }
  162. return b;
  163. }
  164. /*
  165. * Displays a GUID
  166. */
  167. BOOL
  168. PrintGuid(
  169. GUID *pguid)
  170. {
  171. ULONG i;
  172. PRINTF( "%08x-%04x-%04x", pguid->Data1, pguid->Data2, pguid->Data3 );
  173. for (i = 0; i < 8; i++) {
  174. PRINTF("%02x",pguid->Data4[i]);
  175. }
  176. return( TRUE );
  177. }
  178. /*
  179. * Displays a LARGE_INTEGER
  180. */
  181. BOOL
  182. PrintLargeInt(
  183. LARGE_INTEGER *bigint)
  184. {
  185. PRINTF( "%08x:%08x", bigint->HighPart, bigint->LowPart);
  186. return( TRUE );
  187. }
  188. /*
  189. * Displays all the fields of a given struct. This is the driver routine that is called
  190. * with the appropriate descriptor array to display all the fields in a given struct.
  191. */
  192. LPSTR LibCommands[] = {
  193. "help -- This command ",
  194. "version -- Version of extension ",
  195. "dump <Struct Type Name>@<address expr> ",
  196. "columns <d> -- controls the number of columns in the display ",
  197. 0
  198. };
  199. BOOL
  200. help(
  201. DWORD dwCurrentPC,
  202. PWINDBG_EXTENSION_APIS lpExtensionApis,
  203. LPSTR lpArgumentString
  204. )
  205. {
  206. int i;
  207. PRINTF("\n");
  208. for( i=0; ExtensionNames[i]; i++ )
  209. PRINTF( "%s\n", ExtensionNames[i] );
  210. for( i=0; LibCommands[i]; i++ )
  211. PRINTF( " %s\n", LibCommands[i] );
  212. for( i=0; Extensions[i]; i++) {
  213. PRINTF( " %s\n", Extensions[i] );
  214. }
  215. return TRUE;
  216. }
  217. BOOL
  218. columns(
  219. DWORD dwCurrentPC,
  220. PWINDBG_EXTENSION_APIS lpExtensionApis,
  221. LPSTR lpArgumentString
  222. )
  223. {
  224. ULONG NoOfColumns;
  225. int i;
  226. if (kdextAtoi(lpArgumentString, &i) && i > 0) {
  227. NoOfColumns = (ULONG) i;
  228. if (NoOfColumns > s_MaxNoOfColumns) {
  229. PRINTF( "No. Of Columns exceeds maximum(%ld) -- directive Ignored\n", s_MaxNoOfColumns );
  230. } else {
  231. s_NoOfColumns = NoOfColumns;
  232. }
  233. } else {
  234. PRINTF( "Bad argument to command (%s)", lpArgumentString );
  235. }
  236. return TRUE;
  237. }
  238. BOOL
  239. version
  240. (
  241. DWORD dwCurrentPC,
  242. PWINDBG_EXTENSION_APIS lpExtensionApis,
  243. LPSTR lpArgumentString
  244. )
  245. {
  246. #if VER_DEBUG
  247. char *kind = "checked";
  248. #else
  249. char *kind = "free";
  250. #endif
  251. PRINTF( "Mup debugger extension dll for %s build %u\n", kind, VER_PRODUCTBUILD );
  252. return TRUE;
  253. }
  254. /*
  255. * KD Extensions should not link with the C-Runtime library routines. So,
  256. * we implement a few of the needed ones here.
  257. */
  258. BOOL
  259. kdextAtoi(
  260. LPSTR lpArg,
  261. int *pRet
  262. )
  263. {
  264. int n, cbArg, val = 0;
  265. BOOL fNegative = FALSE;
  266. cbArg = kdextStrlen( lpArg );
  267. if (cbArg > 0) {
  268. for (n = 0; lpArg[n] == ' '; n++) {
  269. ;
  270. }
  271. if (lpArg[n] == '-') {
  272. n++;
  273. fNegative = TRUE;
  274. }
  275. for (; lpArg[n] >= '0' && lpArg[n] <= '9'; n++) {
  276. val *= 10;
  277. val += (int) (lpArg[n] - '0');
  278. }
  279. if (lpArg[n] == 0) {
  280. *pRet = (fNegative ? -val : val);
  281. return( TRUE );
  282. } else {
  283. return( FALSE );
  284. }
  285. } else {
  286. return( FALSE );
  287. }
  288. }
  289. int
  290. kdextStrlen(
  291. LPSTR lpsz
  292. )
  293. {
  294. int c;
  295. if (lpsz == NULL) {
  296. c = 0;
  297. } else {
  298. for (c = 0; lpsz[c] != 0; c++) {
  299. ;
  300. }
  301. }
  302. return( c );
  303. }
  304. #define UPCASE_CHAR(c) \
  305. ( (((c) >= 'a') && ((c) <= 'z')) ? ((c) - 'a' + 'A') : (c) )
  306. int
  307. kdextStrnicmp(
  308. LPSTR lpsz1,
  309. LPSTR lpsz2,
  310. int cLen
  311. )
  312. {
  313. int nDif, i;
  314. for (i = nDif = 0; nDif == 0 && i < cLen; i++) {
  315. nDif = UPCASE_CHAR(lpsz1[i]) - UPCASE_CHAR(lpsz2[i]);
  316. }
  317. return( nDif );
  318. }
  319.