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.

550 lines
12 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 2001
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Utility library used for the various debugger extensions in this library.
  7. Author:
  8. Peter Wieland (peterwie) 16-Oct-1995
  9. ervinp
  10. Environment:
  11. User Mode.
  12. Revision History:
  13. --*/
  14. #include "pch.h"
  15. #include "ideport.h"
  16. PUCHAR devicePowerStateNames[] = {
  17. "PowerDeviceUnspecified",
  18. "PowerDeviceD0",
  19. "PowerDeviceD1",
  20. "PowerDeviceD2",
  21. "PowerDeviceD3",
  22. "PowerDeviceMaximum",
  23. "Invalid"
  24. };
  25. FLAG_NAME SrbFlags[] = {
  26. FLAG_NAME(SRB_FLAGS_QUEUE_ACTION_ENABLE),
  27. FLAG_NAME(SRB_FLAGS_DISABLE_DISCONNECT),
  28. FLAG_NAME(SRB_FLAGS_DISABLE_SYNCH_TRANSFER),
  29. FLAG_NAME(SRB_FLAGS_BYPASS_FROZEN_QUEUE),
  30. FLAG_NAME(SRB_FLAGS_DISABLE_AUTOSENSE),
  31. FLAG_NAME(SRB_FLAGS_DATA_IN),
  32. FLAG_NAME(SRB_FLAGS_DATA_OUT),
  33. FLAG_NAME(SRB_FLAGS_NO_DATA_TRANSFER),
  34. FLAG_NAME(SRB_FLAGS_UNSPECIFIED_DIRECTION),
  35. FLAG_NAME(SRB_FLAGS_NO_QUEUE_FREEZE),
  36. FLAG_NAME(SRB_FLAGS_ADAPTER_CACHE_ENABLE),
  37. FLAG_NAME(SRB_FLAGS_IS_ACTIVE),
  38. FLAG_NAME(SRB_FLAGS_ALLOCATED_FROM_ZONE),
  39. FLAG_NAME(SRB_FLAGS_SGLIST_FROM_POOL),
  40. FLAG_NAME(SRB_FLAGS_BYPASS_LOCKED_QUEUE),
  41. FLAG_NAME(SRB_FLAGS_NO_KEEP_AWAKE),
  42. {0,0}
  43. };
  44. FLAG_NAME LuFlags[] = {
  45. FLAG_NAME(PD_QUEUE_FROZEN),
  46. FLAG_NAME(PD_LOGICAL_UNIT_IS_ACTIVE),
  47. FLAG_NAME(PD_NEED_REQUEST_SENSE),
  48. FLAG_NAME(PD_LOGICAL_UNIT_IS_BUSY),
  49. FLAG_NAME(PD_QUEUE_IS_FULL),
  50. FLAG_NAME(PD_RESCAN_ACTIVE),
  51. {0, 0}
  52. };
  53. FLAG_NAME PortFlags[] = {
  54. FLAG_NAME(PD_DEVICE_IS_BUSY),
  55. FLAG_NAME(PD_NOTIFICATION_REQUIRED),
  56. FLAG_NAME(PD_READY_FOR_NEXT_REQUEST),
  57. FLAG_NAME(PD_FLUSH_ADAPTER_BUFFERS),
  58. FLAG_NAME(PD_MAP_TRANSFER),
  59. FLAG_NAME(PD_LOG_ERROR),
  60. FLAG_NAME(PD_RESET_HOLD),
  61. FLAG_NAME(PD_HELD_REQUEST),
  62. FLAG_NAME(PD_RESET_REPORTED),
  63. FLAG_NAME(PD_PENDING_DEVICE_REQUEST),
  64. FLAG_NAME(PD_DISCONNECT_RUNNING),
  65. FLAG_NAME(PD_DISABLE_CALL_REQUEST),
  66. FLAG_NAME(PD_DISABLE_INTERRUPTS),
  67. FLAG_NAME(PD_ENABLE_CALL_REQUEST),
  68. FLAG_NAME(PD_TIMER_CALL_REQUEST),
  69. FLAG_NAME(PD_ALL_DEVICE_MISSING),
  70. FLAG_NAME(PD_RESET_REQUEST),
  71. {0,0}
  72. };
  73. FLAG_NAME DevFlags[] = {
  74. FLAG_NAME(DFLAGS_DEVICE_PRESENT),
  75. FLAG_NAME(DFLAGS_ATAPI_DEVICE),
  76. FLAG_NAME(DFLAGS_TAPE_DEVICE),
  77. FLAG_NAME(DFLAGS_INT_DRQ),
  78. FLAG_NAME(DFLAGS_REMOVABLE_DRIVE),
  79. FLAG_NAME(DFLAGS_MEDIA_STATUS_ENABLED),
  80. FLAG_NAME(DFLAGS_USE_DMA),
  81. FLAG_NAME(DFLAGS_LBA),
  82. FLAG_NAME(DFLAGS_MULTI_LUN_INITED),
  83. FLAG_NAME(DFLAGS_MSN_SUPPORT),
  84. FLAG_NAME(DFLAGS_AUTO_EJECT_ZIP),
  85. FLAG_NAME(DFLAGS_WD_MODE),
  86. FLAG_NAME(DFLAGS_LS120_FORMAT),
  87. FLAG_NAME(DFLAGS_USE_UDMA),
  88. FLAG_NAME(DFLAGS_IDENTIFY_VALID),
  89. FLAG_NAME(DFLAGS_IDENTIFY_INVALID),
  90. FLAG_NAME(DFLAGS_RDP_SET),
  91. FLAG_NAME(DFLAGS_SONY_MEMORYSTICK),
  92. FLAG_NAME(DFLAGS_48BIT_LBA),
  93. {0,0}
  94. };
  95. VOID
  96. GetAddress(
  97. IN PCSTR Args,
  98. OUT PULONG64 Address
  99. )
  100. {
  101. UCHAR addressBuffer[256];
  102. addressBuffer[0] = '\0';
  103. sscanf(Args, "%s", addressBuffer);
  104. addressBuffer[255] = '\0';
  105. *Address = 0;
  106. if (addressBuffer[0] != '\0') {
  107. //
  108. // they provided an address
  109. //
  110. *Address = (ULONG64)GetExpression(addressBuffer);
  111. //
  112. // if that still doesn't parse, print an error
  113. //
  114. if (*Address==0) {
  115. dprintf("An error occured trying to evaluate the address\n");
  116. *Address = 0;
  117. return;
  118. }
  119. }
  120. return;
  121. }
  122. VOID
  123. GetAddressAndDetailLevel(
  124. IN PCSTR Args,
  125. OUT PULONG64 Address,
  126. OUT PLONG Detail
  127. )
  128. {
  129. UCHAR addressBuffer[256];
  130. UCHAR detailBuffer[256];
  131. addressBuffer[0] = '\0';
  132. detailBuffer[0] = '\0';
  133. sscanf(Args, "%s %s", addressBuffer, detailBuffer);
  134. addressBuffer[255] = '\0';
  135. detailBuffer[255] = '\0';
  136. *Address = 0;
  137. *Detail = 0;
  138. if (addressBuffer[0] != '\0') {
  139. //
  140. // they provided an address
  141. //
  142. *Address = (ULONG64) GetExpression(addressBuffer);
  143. //
  144. // if that still doesn't parse, print an error
  145. //
  146. if (*Address==0) {
  147. dprintf("An error occured trying to evaluate the address\n");
  148. *Address = 0;
  149. *Detail = 0;
  150. return;
  151. }
  152. //
  153. // if they provided a detail level get it.
  154. //
  155. if (detailBuffer[0] == '\0') {
  156. *Detail = 0;
  157. } else {
  158. *Detail = (ULONG) GetExpression(detailBuffer);
  159. }
  160. }
  161. return;
  162. }
  163. VOID
  164. GetAddressAndDetailLevel64(
  165. IN PCSTR Args,
  166. OUT PULONG64 Address,
  167. OUT PLONG Detail
  168. )
  169. {
  170. UCHAR addressBuffer[256];
  171. UCHAR detailBuffer[256];
  172. addressBuffer[0] = '\0';
  173. detailBuffer[0] = '\0';
  174. sscanf(Args, "%s %s", addressBuffer, detailBuffer);
  175. addressBuffer[255] = '\0';
  176. detailBuffer[255] = '\0';
  177. *Address = 0;
  178. *Detail = 0;
  179. if (addressBuffer[0] != '\0') {
  180. //
  181. // they provided an address
  182. //
  183. *Address = GetExpression(addressBuffer);
  184. //
  185. // if that still doesn't parse, print an error
  186. //
  187. if (*Address==0) {
  188. dprintf("Error while trying to evaluate the address.\n");
  189. *Address = 0;
  190. *Detail = 0;
  191. return;
  192. }
  193. //
  194. // if they provided a detail level get it.
  195. //
  196. if (detailBuffer[0] == '\0') {
  197. *Detail = 0;
  198. }
  199. else {
  200. *Detail = (ULONG)GetExpression(detailBuffer);
  201. }
  202. }
  203. return;
  204. }
  205. PUCHAR
  206. DevicePowerStateToString(
  207. IN DEVICE_POWER_STATE State
  208. )
  209. {
  210. if(State > PowerDeviceMaximum) {
  211. return devicePowerStateNames[PowerDeviceMaximum + 1];
  212. } else {
  213. return devicePowerStateNames[(UCHAR) State];
  214. }
  215. }
  216. /*
  217. * xdprintf
  218. *
  219. * Prints formatted text with leading spaces.
  220. *
  221. * WARNING: DOES NOT HANDLE ULONG64 PROPERLY.
  222. */
  223. VOID
  224. xdprintf(
  225. ULONG Depth,
  226. PCCHAR S,
  227. ...
  228. )
  229. {
  230. va_list ap;
  231. ULONG i;
  232. CCHAR DebugBuffer[256];
  233. for (i=0; i<Depth; i++) {
  234. dprintf (" ");
  235. }
  236. va_start(ap, S);
  237. vsprintf(DebugBuffer, S, ap);
  238. dprintf (DebugBuffer);
  239. va_end(ap);
  240. }
  241. VOID
  242. DumpFlags(
  243. ULONG Depth,
  244. PUCHAR Name,
  245. ULONG Flags,
  246. PFLAG_NAME FlagTable
  247. )
  248. {
  249. ULONG i;
  250. ULONG mask = 0;
  251. ULONG count = 0;
  252. UCHAR prolog[64];
  253. sprintf(prolog, "%s (0x%08x): ", Name, Flags);
  254. xdprintf(Depth, "%s", prolog);
  255. if(Flags == 0) {
  256. dprintf("\n");
  257. return;
  258. }
  259. memset(prolog, ' ', strlen(prolog));
  260. for(i = 0; FlagTable[i].Name != 0; i++) {
  261. PFLAG_NAME flag = &(FlagTable[i]);
  262. mask |= flag->Flag;
  263. if((Flags & flag->Flag) == flag->Flag) {
  264. //
  265. // print trailing comma
  266. //
  267. if(count != 0) {
  268. dprintf(", ");
  269. //
  270. // Only print two flags per line.
  271. //
  272. if((count % 2) == 0) {
  273. dprintf("\n");
  274. xdprintf(Depth, "%s", prolog);
  275. }
  276. }
  277. dprintf("%s", flag->Name);
  278. count++;
  279. }
  280. }
  281. dprintf("\n");
  282. if((Flags & (~mask)) != 0) {
  283. xdprintf(Depth, "%sUnknown flags %#010lx\n", prolog, (Flags & (~mask)));
  284. }
  285. return;
  286. }
  287. BOOLEAN
  288. GetAnsiString(
  289. IN ULONG64 Address,
  290. IN PUCHAR Buffer,
  291. IN OUT PULONG Length
  292. )
  293. {
  294. ULONG i = 0;
  295. //
  296. // Grab the string in 64 character chunks until we find a NULL or the
  297. // read fails.
  298. //
  299. while((i < *Length) && (!CheckControlC())) {
  300. ULONG transferSize;
  301. ULONG result;
  302. if(*Length - i < 128) {
  303. transferSize = *Length - i;
  304. } else {
  305. transferSize = 128;
  306. }
  307. if(!ReadMemory(Address + i,
  308. Buffer + i,
  309. transferSize,
  310. &result)) {
  311. //
  312. // read failed and we didn't find the NUL the last time. Don't
  313. // expect to find it this time.
  314. // BUGBUG - figure out if i should expect it this time.
  315. //
  316. *Length = i;
  317. return FALSE;
  318. } else {
  319. ULONG j;
  320. //
  321. // Scan from where we left off looking for that NUL character.
  322. //
  323. for(j = 0; j < transferSize; j++) {
  324. if(Buffer[i + j] == '\0') {
  325. *Length = i + j;
  326. return TRUE;
  327. }
  328. }
  329. }
  330. i += transferSize;
  331. }
  332. //
  333. // We never found the NUL. Don't need to update Length since it's currently
  334. // equal to i.
  335. //
  336. return FALSE;
  337. }
  338. /*
  339. * GetULONGField
  340. *
  341. * Return the field or -1 in case of error.
  342. * Yes, it screws up if the field is actually -1.
  343. */
  344. ULONG64 GetULONGField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  345. {
  346. ULONG64 result;
  347. ULONG dbgStat;
  348. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(ULONG64), &result);
  349. if (dbgStat != 0){
  350. dprintf("\n GetULONGField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
  351. dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
  352. result = BAD_VALUE;
  353. }
  354. return result;
  355. }
  356. /*
  357. * GetUSHORTField
  358. *
  359. * Return the field or -1 in case of error.
  360. * Yes, it screws up if the field is actually -1.
  361. */
  362. USHORT GetUSHORTField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  363. {
  364. USHORT result;
  365. ULONG dbgStat;
  366. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(USHORT), &result);
  367. if (dbgStat != 0){
  368. dprintf("\n GetUSHORTField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
  369. dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
  370. result = (USHORT)BAD_VALUE;
  371. }
  372. return result;
  373. }
  374. /*
  375. * GetUCHARField
  376. *
  377. * Return the field or -1 in case of error.
  378. * Yes, it screws up if the field is actually -1.
  379. */
  380. UCHAR GetUCHARField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  381. {
  382. UCHAR result;
  383. ULONG dbgStat;
  384. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(UCHAR), &result);
  385. if (dbgStat != 0){
  386. dprintf("\n GetUCHARField: GetFieldData failed with %xh retrieving field '%s' of struct '%s' @ %08p, returning bogus field value %08xh.\n",
  387. dbgStat, FieldName, StructType, StructAddr, BAD_VALUE);
  388. result = (UCHAR)BAD_VALUE;
  389. }
  390. return result;
  391. }
  392. ULONG64 GetFieldAddr(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  393. {
  394. ULONG64 result;
  395. ULONG offset;
  396. ULONG dbgStat;
  397. dbgStat = GetFieldOffset(StructType, FieldName, &offset);
  398. if (dbgStat == 0){
  399. result = StructAddr+offset;
  400. }
  401. else {
  402. dprintf("\n GetFieldAddr: GetFieldOffset failed with %xh retrieving offset of struct '%s' (@ %08p) field '%s'.\n",
  403. dbgStat, StructType, StructAddr, FieldName);
  404. result = BAD_VALUE;
  405. }
  406. return result;
  407. }
  408. ULONG64 GetContainingRecord(ULONG64 FieldAddr, LPCSTR StructType, LPCSTR FieldName)
  409. {
  410. ULONG64 result;
  411. ULONG offset;
  412. ULONG dbgStat;
  413. dbgStat = GetFieldOffset(StructType, FieldName, &offset);
  414. if (dbgStat == 0){
  415. result = FieldAddr-offset;
  416. }
  417. else {
  418. dprintf("\n GetContainingRecord: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s', returning bogus address %08xh.\n", dbgStat, StructType, FieldName, BAD_VALUE);
  419. result = BAD_VALUE;
  420. }
  421. return result;
  422. }