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.

638 lines
14 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Wesley Witt (wesw) 15-Aug-1993
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. ULONG
  16. GetBitFieldOffset (
  17. IN LPSTR Type,
  18. IN LPSTR Field,
  19. OUT PULONG pOffset,
  20. OUT PULONG pSize
  21. )
  22. {
  23. FIELD_INFO flds = {
  24. Field, "", 0,
  25. DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS | DBG_DUMP_FIELD_SIZE_IN_BITS,
  26. 0, NULL};
  27. SYM_DUMP_PARAM Sym = {
  28. sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
  29. NULL, NULL, NULL, 1, &flds
  30. };
  31. ULONG Err, i=0;
  32. Sym.nFields = 1;
  33. Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  34. *pOffset = (ULONG) (flds.address - Sym.addr);
  35. *pSize = flds.size;
  36. return Err;
  37. }
  38. ULONG
  39. GetFieldOffsetEx (
  40. IN LPSTR Type,
  41. IN LPSTR Field,
  42. OUT PULONG pOffset,
  43. OUT PULONG pSize
  44. )
  45. {
  46. FIELD_INFO flds = {
  47. Field, "", 0,
  48. DBG_DUMP_FIELD_FULL_NAME | DBG_DUMP_FIELD_RETURN_ADDRESS,
  49. 0, NULL};
  50. SYM_DUMP_PARAM Sym = {
  51. sizeof (SYM_DUMP_PARAM), Type, DBG_DUMP_NO_PRINT, 0,
  52. NULL, NULL, NULL, 1, &flds
  53. };
  54. ULONG Err, i=0;
  55. Sym.nFields = 1;
  56. Err = Ioctl( IG_DUMP_SYMBOL_INFO, &Sym, Sym.size );
  57. *pOffset = (ULONG) (flds.address - Sym.addr);
  58. *pSize = flds.size;
  59. return Err;
  60. } // GetFieldOffsetEx()
  61. ULONG
  62. GetUlongFromAddress (
  63. ULONG64 Location
  64. )
  65. {
  66. ULONG Value;
  67. ULONG result;
  68. if ((!ReadMemory(Location,&Value,sizeof(ULONG),&result)) ||
  69. (result < sizeof(ULONG))) {
  70. dprintf("GetUlongFromAddress: unable to read from %p\n", Location);
  71. return 0;
  72. }
  73. return Value;
  74. }
  75. BYTE
  76. GetByteFromAddress (
  77. ULONG64 Location
  78. )
  79. {
  80. BYTE Value;
  81. ULONG result;
  82. if ((!ReadMemory(Location,&Value,sizeof(Value),&result)) ||
  83. (result < sizeof(Value))) {
  84. dprintf("GetByteFromAddress: unable to read from %p\n", Location);
  85. return 0;
  86. }
  87. return Value;
  88. }
  89. ULONG64
  90. GetPointerFromAddress (
  91. ULONG64 Location
  92. )
  93. {
  94. ULONG64 Value;
  95. ULONG result;
  96. if (!ReadPointer( Location, &Value )) {
  97. dprintf( "GetPointerFromAddress: unable to read from %p\n", Location );
  98. return 0;
  99. }
  100. return Value;
  101. }
  102. ULONG
  103. GetUlongValue (
  104. PCHAR String
  105. )
  106. {
  107. ULONG64 Location;
  108. ULONG Value;
  109. ULONG result;
  110. Location = GetExpression( String );
  111. if (!Location) {
  112. dprintf("unable to get %s\n",String);
  113. return 0;
  114. }
  115. return GetUlongFromAddress( Location );
  116. }
  117. BYTE
  118. GetByteValue (
  119. PCHAR String
  120. )
  121. {
  122. ULONG64 Location;
  123. ULONG Value;
  124. ULONG result;
  125. Location = GetExpression( String );
  126. if (!Location) {
  127. dprintf("unable to get %s\n",String);
  128. return 0;
  129. }
  130. return GetByteFromAddress( Location );
  131. }
  132. ULONG64
  133. GetPointerValue (
  134. PCHAR String
  135. )
  136. {
  137. ULONG64 Location, Val=0;
  138. Location = GetExpression( String );
  139. if (!Location) {
  140. dprintf("unable to get %s\n",String);
  141. return 0;
  142. }
  143. ReadPointer(Location, &Val);
  144. return Val;
  145. }
  146. ULONG64
  147. GetGlobalFromAddress (
  148. ULONG64 Location,
  149. ULONG Size
  150. )
  151. {
  152. ULONG64 value;
  153. ULONG result;
  154. value = 0;
  155. if (Size > sizeof(value))
  156. {
  157. Size = sizeof(value);
  158. }
  159. if ((!ReadMemory(Location,&value,Size,&result)) || (result < Size)) {
  160. dprintf("GetGlobalFromAddress: unable to read from %p\n", Location);
  161. return 0;
  162. }
  163. return value;
  164. } // GetGlobalFromAddress()
  165. ULONG64
  166. GetGlobalValue (
  167. PCHAR String
  168. )
  169. {
  170. ULONG64 location;
  171. ULONG size;
  172. location = GetExpression( String );
  173. if (!location) {
  174. dprintf("GetGlobalValue: unable to get %s\n",String);
  175. return 0;
  176. }
  177. size = GetTypeSize( String );
  178. if (!size) {
  179. dprintf("GetGlobalValue: unable to get %s type size\n",String);
  180. return 0;
  181. }
  182. return GetGlobalFromAddress( location, size );
  183. } // GetGlobalValue()
  184. HRESULT
  185. GetGlobalEx(
  186. PCHAR String,
  187. PVOID OutValue,
  188. ULONG OutSize
  189. )
  190. {
  191. ULONG64 location;
  192. ULONG size;
  193. ULONG result;
  194. ZeroMemory( OutValue, OutSize );
  195. location = GetExpression( String );
  196. if (!location) {
  197. return E_INVALIDARG;
  198. }
  199. size = GetTypeSize( String );
  200. if (!size) {
  201. return E_INVALIDARG;
  202. }
  203. if ( size > OutSize ) {
  204. return E_OUTOFMEMORY;
  205. }
  206. if ((!ReadMemory(location,OutValue,size,&result)) || (result < size)) {
  207. return E_FAIL;
  208. }
  209. return S_OK;
  210. } // GetGlobalEx()
  211. BOOLEAN
  212. DbgRtlIsRightChild(
  213. ULONG64 pLinks,
  214. ULONG64 Parent
  215. )
  216. {
  217. ULONG64 RightChild;
  218. if (Parent == pLinks) {
  219. return FALSE;
  220. }
  221. if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "RightChild", RightChild)) {
  222. return FALSE;
  223. }
  224. if (RightChild == pLinks) {
  225. return TRUE;
  226. }
  227. return FALSE;
  228. }
  229. BOOLEAN
  230. DbgRtlIsLeftChild(
  231. ULONG64 pLinks,
  232. ULONG64 Parent
  233. )
  234. {
  235. ULONG64 LeftChild;
  236. if (Parent == pLinks) {
  237. return FALSE;
  238. }
  239. if (GetFieldValue(Parent, "RTL_SPLAY_LINKS", "LeftChild", LeftChild)) {
  240. return FALSE;
  241. }
  242. if (LeftChild == pLinks) {
  243. return TRUE;
  244. }
  245. return FALSE;
  246. }
  247. ULONG
  248. DumpSplayTree(
  249. IN ULONG64 pSplayLinks,
  250. IN PDUMP_SPLAY_NODE_FN DumpNodeFn
  251. )
  252. /*++
  253. Purpose:
  254. Perform an in-order iteration across a splay tree, calling a
  255. user supplied function with a pointer to each RTL_SPLAY_LINKS
  256. structure encountered in the tree, and the level in the tree
  257. at which it was encountered (zero based).
  258. Arguments:
  259. pSplayLinks - pointer to root of a splay tree
  260. DumpNodeFn - user supplied dumping function
  261. Returns:
  262. Count of nodes encountered in the tree.
  263. Notes:
  264. Errors reading memory do not terminate the iteration if more
  265. work is possible.
  266. Consumes the Control-C flag to terminate possible loops in
  267. corrupt structures.
  268. --*/
  269. {
  270. ULONG Level = 0;
  271. ULONG NodeCount = 0;
  272. if (pSplayLinks) {
  273. ULONG64 LeftChild, RightChild, Parent, Current;
  274. //
  275. // Retrieve the root links, find the leftmost node in the tree
  276. //
  277. if (GetFieldValue(Current = pSplayLinks,
  278. "RTL_SPLAY_LINKS",
  279. "LeftChild",
  280. LeftChild)) {
  281. return NodeCount;
  282. }
  283. while (LeftChild != 0) {
  284. if ( CheckControlC() ) {
  285. return NodeCount;
  286. }
  287. if (GetFieldValue(Current = LeftChild,
  288. "RTL_SPLAY_LINKS",
  289. "LeftChild",
  290. LeftChild)) {
  291. //
  292. // We can try to continue from this
  293. //
  294. break;
  295. }
  296. Level++;
  297. }
  298. while (TRUE) {
  299. if ( CheckControlC() ) {
  300. return NodeCount;
  301. }
  302. NodeCount++;
  303. pSplayLinks = Current;
  304. (*DumpNodeFn)(pSplayLinks, Level);
  305. /*
  306. first check to see if there is a right subtree to the input link
  307. if there is then the real successor is the left most node in
  308. the right subtree. That is find and return P in the following diagram
  309. Links
  310. \
  311. .
  312. .
  313. .
  314. /
  315. P
  316. \
  317. */
  318. GetFieldValue(Current, "RTL_SPLAY_LINKS", "RightChild", RightChild);
  319. if (RightChild != 0) {
  320. if (GetFieldValue(Current = RightChild,
  321. "RTL_SPLAY_LINKS",
  322. "RightChild",
  323. RightChild)) {
  324. //
  325. // We've failed to step through to a successor, so
  326. // there is no more to do
  327. //
  328. return NodeCount;
  329. }
  330. Level++;
  331. GetFieldValue(Current,"RTL_SPLAY_LINKS","LeftChild",LeftChild);
  332. while (LeftChild != 0) {
  333. if ( CheckControlC() ) {
  334. return NodeCount;
  335. }
  336. if (GetFieldValue(Current = LeftChild,
  337. "RTL_SPLAY_LINKS",
  338. "LeftChild",
  339. LeftChild)) {
  340. //
  341. // We can continue from this
  342. //
  343. break;
  344. }
  345. Level++;
  346. }
  347. } else {
  348. /*
  349. we do not have a right child so check to see if have a parent and if
  350. so find the first ancestor that we are a left decendent of. That
  351. is find and return P in the following diagram
  352. P
  353. /
  354. .
  355. .
  356. .
  357. Links
  358. */
  359. //
  360. // If the IsLeft or IsRight functions fail to read through a parent
  361. // pointer, then we will quickly exit through the break below
  362. //
  363. GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
  364. while (DbgRtlIsRightChild(Current, Parent)) {
  365. if ( CheckControlC() ) {
  366. return NodeCount;
  367. }
  368. Level--;
  369. pSplayLinks = (Current = Parent);
  370. }
  371. GetFieldValue(Current, "RTL_SPLAY_LINKS", "Parent", Parent);
  372. if (!DbgRtlIsLeftChild(Current, Parent)) {
  373. //
  374. // we do not have a real successor so we break out
  375. //
  376. break;
  377. } else {
  378. Level--;
  379. pSplayLinks = (Current = Parent);
  380. }
  381. }
  382. }
  383. }
  384. return NodeCount;
  385. }
  386. VOID
  387. DumpUnicode64(
  388. UNICODE_STRING64 u
  389. )
  390. {
  391. UNICODE_STRING v;
  392. DWORD BytesRead;
  393. if (u.MaximumLength > 0x1000)
  394. {
  395. u.MaximumLength = 0x1000;
  396. }
  397. // dprintf("L %x, M %x, B %p ", u.Length, u.MaximumLength, u.Buffer);
  398. if ((u.Length <= u.MaximumLength) &&
  399. (u.Buffer) &&
  400. (u.Length > 0)) {
  401. v.Buffer = LocalAlloc(LPTR, u.MaximumLength+sizeof(WCHAR));
  402. if (v.Buffer != NULL) {
  403. v.MaximumLength = u.MaximumLength;
  404. v.Length = u.Length;
  405. if (ReadMemory(u.Buffer,
  406. v.Buffer,
  407. u.Length,
  408. (PULONG) &u.Buffer)) {
  409. v.Buffer[v.MaximumLength/sizeof(WCHAR)] = 0;
  410. dprintf("%wZ", &v);
  411. } else {
  412. dprintf("<???>");
  413. }
  414. LocalFree(v.Buffer);
  415. return;
  416. }
  417. }
  418. }
  419. BOOLEAN
  420. IsHexNumber(
  421. const char *szExpression
  422. )
  423. {
  424. if (!szExpression[0]) {
  425. return FALSE ;
  426. }
  427. for(;*szExpression; szExpression++) {
  428. if ((*szExpression)< '0') { return FALSE ; }
  429. else if ((*szExpression)> 'f') { return FALSE ; }
  430. else if ((*szExpression)>='a') { continue ; }
  431. else if ((*szExpression)> 'F') { return FALSE ; }
  432. else if ((*szExpression)<='9') { continue ; }
  433. else if ((*szExpression)>='A') { continue ; }
  434. else { return FALSE ; }
  435. }
  436. return TRUE ;
  437. }
  438. BOOLEAN
  439. IsDecNumber(
  440. const char *szExpression
  441. )
  442. {
  443. if (!szExpression[0]) {
  444. return FALSE ;
  445. }
  446. while(*szExpression) {
  447. if ((*szExpression)<'0') { return FALSE ; }
  448. else if ((*szExpression)>'9') { return FALSE ; }
  449. szExpression ++ ;
  450. }
  451. return TRUE ;
  452. }
  453. ULONG64
  454. UtilStringToUlong64 (
  455. UCHAR *String
  456. )
  457. {
  458. UCHAR LowDword[9], HighDword[9];
  459. ZeroMemory (HighDword, sizeof (HighDword));
  460. ZeroMemory (LowDword, sizeof (LowDword));
  461. if (strlen (String) > 8) {
  462. memcpy (LowDword, (void *) &String[strlen (String) - 8], 8);
  463. memcpy (HighDword, (void *) &String[0], strlen (String) - 8);
  464. } else {
  465. return strtoul (String, 0, 16);
  466. }
  467. return ((ULONG64) strtoul (HighDword, 0, 16) << 32) + strtoul (LowDword, 0, 16);
  468. }
  469. const char *
  470. getEnumName(
  471. ULONG EnumVal,
  472. PENUM_NAME EnumTable
  473. )
  474. /*++
  475. Routine Description:
  476. Gets the supplied enum value's name in string format
  477. Arguments:
  478. EnumVal - Enum to be retrieved
  479. EnumTable - Table in which the enum is looked up to find
  480. the string to be retrieved (since we can't rely on the debugger)
  481. Return Value:
  482. None
  483. --*/
  484. {
  485. ULONG i;
  486. for (i=0; EnumTable[i].Name != NULL; i++) {
  487. if (EnumTable[i].EnumVal == EnumVal) {
  488. break;
  489. }
  490. }
  491. if (EnumTable[i].Name != NULL) {
  492. return EnumTable[i].Name;
  493. } else {
  494. return "Unknown ";
  495. }
  496. }