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.

429 lines
10 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  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. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #include "classkd.h" // routines that are useful for all class drivers
  15. PUCHAR devicePowerStateNames[] = {
  16. "PowerDeviceUnspecified",
  17. "PowerDeviceD0",
  18. "PowerDeviceD1",
  19. "PowerDeviceD2",
  20. "PowerDeviceD3",
  21. "PowerDeviceMaximum",
  22. "Invalid"
  23. };
  24. char *g_genericErrorHelpStr = "\n" \
  25. "**************************************************************** \n" \
  26. " Make sure you have _private_ symbols for classpnp.sys loaded.\n" \
  27. " The FDO parameter should be the upper AttachedDevice of the disk/cdrom/etc PDO\n" \
  28. " as returned by '!devnode 0 1 {disk|cdrom|4mmdat|etc}'.\n" \
  29. "**************************************************************** \n\n" \
  30. ;
  31. PUCHAR
  32. DevicePowerStateToString(
  33. IN DEVICE_POWER_STATE State
  34. )
  35. {
  36. ULONG stateIndex = (ULONG)State;
  37. if(stateIndex > PowerDeviceMaximum) {
  38. return "Invalid";
  39. } else {
  40. return devicePowerStateNames[stateIndex];
  41. }
  42. }
  43. /*
  44. * xdprintf
  45. *
  46. * Prints formatted text with leading spaces.
  47. *
  48. * WARNING: DOES NOT HANDLE ULONG64 PROPERLY.
  49. */
  50. VOID
  51. xdprintf(
  52. ULONG Depth,
  53. PCCHAR Format,
  54. ...
  55. )
  56. {
  57. va_list args;
  58. ULONG i;
  59. CCHAR DebugBuffer[256];
  60. for (i=0; i<Depth; i++) {
  61. dprintf (" ");
  62. }
  63. va_start(args, Format);
  64. _vsnprintf(DebugBuffer, 255, Format, args);
  65. dprintf (DebugBuffer);
  66. va_end(args);
  67. }
  68. VOID
  69. DumpFlags(
  70. ULONG Depth,
  71. PUCHAR Name,
  72. ULONG Flags,
  73. PFLAG_NAME FlagTable
  74. )
  75. {
  76. ULONG i;
  77. ULONG mask = 0;
  78. ULONG count = 0;
  79. UCHAR prolog[64] = {0};
  80. _snprintf(prolog, sizeof(prolog)-1, "%s (0x%08x): ", Name, Flags);
  81. xdprintf(Depth, "%s", prolog);
  82. if(Flags == 0) {
  83. dprintf("\n");
  84. return;
  85. }
  86. memset(prolog, ' ', strlen(prolog));
  87. for(i = 0; FlagTable[i].Name != 0; i++) {
  88. PFLAG_NAME flag = &(FlagTable[i]);
  89. mask |= flag->Flag;
  90. if((Flags & flag->Flag) == flag->Flag) {
  91. //
  92. // print trailing comma
  93. //
  94. if(count != 0) {
  95. dprintf(", ");
  96. //
  97. // Only print two flags per line.
  98. //
  99. if((count % 2) == 0) {
  100. dprintf("\n");
  101. xdprintf(Depth, "%s", prolog);
  102. }
  103. }
  104. dprintf("%s", flag->Name);
  105. count++;
  106. }
  107. }
  108. dprintf("\n");
  109. if((Flags & (~mask)) != 0) {
  110. xdprintf(Depth, "%sUnknown flags %#010lx\n", prolog, (Flags & (~mask)));
  111. }
  112. return;
  113. }
  114. BOOLEAN
  115. GetAnsiString(
  116. IN ULONG64 Address,
  117. IN PUCHAR Buffer,
  118. IN OUT PULONG Length
  119. )
  120. {
  121. ULONG i = 0;
  122. //
  123. // Grab the string in 128 character chunks until we find a NULL or the read fails.
  124. //
  125. while((i < *Length) && (!CheckControlC())) {
  126. ULONG transferSize;
  127. ULONG result;
  128. if(*Length - i < 128) {
  129. transferSize = *Length - i;
  130. } else {
  131. transferSize = 128;
  132. }
  133. if(!ReadMemory(Address + i,
  134. Buffer + i,
  135. transferSize,
  136. &result)) {
  137. //
  138. // read failed and we didn't find the NUL the last time. Don't
  139. // expect to find it this time.
  140. //
  141. *Length = i;
  142. return FALSE;
  143. } else {
  144. ULONG j;
  145. //
  146. // Scan from where we left off looking for that NUL character.
  147. //
  148. for(j = 0; j < transferSize; j++) {
  149. if(Buffer[i + j] == '\0') {
  150. *Length = i + j;
  151. return TRUE;
  152. }
  153. }
  154. }
  155. i += transferSize;
  156. }
  157. /*
  158. * We copied all the bytes allowed and did not hit the NUL character.
  159. * Insert a NUL character so returned string is terminated.
  160. */
  161. if (i > 0){
  162. Buffer[i-1] = '\0';
  163. }
  164. *Length = i;
  165. return FALSE;
  166. }
  167. PCHAR
  168. GuidToString(
  169. GUID* Guid
  170. )
  171. {
  172. static CHAR Buffer [64];
  173. sprintf (Buffer,
  174. "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
  175. Guid->Data1,
  176. Guid->Data2,
  177. Guid->Data3,
  178. Guid->Data4[0],
  179. Guid->Data4[1],
  180. Guid->Data4[2],
  181. Guid->Data4[3],
  182. Guid->Data4[4],
  183. Guid->Data4[5],
  184. Guid->Data4[6],
  185. Guid->Data4[7]
  186. );
  187. return Buffer;
  188. }
  189. ULONG64
  190. GetDeviceExtension(
  191. ULONG64 address
  192. )
  193. /*++
  194. Routine Description:
  195. The function accepts the address of either a device object or a device
  196. extension. If the supplied address is that of a device object, the
  197. device extension is retrieved and returned. If the address is that of
  198. a device extension, the address is returned unmodified.
  199. Arguments:
  200. Address - address of a device extension or a device object
  201. Return Value:
  202. The address of the device extension or 0 if an error occurs.
  203. --*/
  204. {
  205. ULONG result;
  206. CSHORT Type;
  207. ULONG64 Address = address;
  208. //
  209. // The supplied address may be either the address of a device object or the
  210. // address of a device extension. To distinguish which, we treat the
  211. // address as a device object and read what would be its type field. If
  212. // the
  213. //
  214. result = GetFieldData(Address,
  215. "scsiport!_DEVICE_OBJECT",
  216. "Type",
  217. sizeof(CSHORT),
  218. &Type
  219. );
  220. if (result) {
  221. SCSIKD_PRINT_ERROR(result);
  222. return 0;
  223. }
  224. //
  225. // See if the supplied address holds a device object. If it does, read the
  226. // address of the device extension. Otherwise, we assume the supplied
  227. // addres holds a device extension and we use it directly.
  228. //
  229. if (Type == IO_TYPE_DEVICE) {
  230. result = GetFieldData(Address,
  231. "scsiport!_DEVICE_OBJECT",
  232. "DeviceExtension",
  233. sizeof(ULONG64),
  234. &Address
  235. );
  236. if (result) {
  237. SCSIKD_PRINT_ERROR(result);
  238. return 0;
  239. }
  240. }
  241. return Address;
  242. }
  243. /*
  244. * GetULONGField
  245. *
  246. * Return the field or -1 in case of error.
  247. * Yes, it screws up if the field is actually -1.
  248. */
  249. ULONG64 GetULONGField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  250. {
  251. ULONG64 result;
  252. ULONG dbgStat;
  253. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(ULONG64), &result);
  254. if (dbgStat != 0){
  255. dprintf("\n GetULONGField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE);
  256. dprintf(g_genericErrorHelpStr);
  257. result = BAD_VALUE;
  258. }
  259. return result;
  260. }
  261. /*
  262. * GetUSHORTField
  263. *
  264. * Return the field or -1 in case of error.
  265. * Yes, it screws up if the field is actually -1.
  266. */
  267. USHORT GetUSHORTField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  268. {
  269. USHORT result;
  270. ULONG dbgStat;
  271. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(USHORT), &result);
  272. if (dbgStat != 0){
  273. dprintf("\n GetUSHORTField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE);
  274. dprintf(g_genericErrorHelpStr);
  275. result = (USHORT)BAD_VALUE;
  276. }
  277. return result;
  278. }
  279. /*
  280. * GetUCHARField
  281. *
  282. * Return the field or -1 in case of error.
  283. * Yes, it screws up if the field is actually -1.
  284. */
  285. UCHAR GetUCHARField(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  286. {
  287. UCHAR result;
  288. ULONG dbgStat;
  289. dbgStat = GetFieldData(StructAddr, StructType, FieldName, sizeof(UCHAR), &result);
  290. if (dbgStat != 0){
  291. dprintf("\n GetUCHARField: GetFieldData failed with %xh retrieving field '%s' of struct '%s', returning bogus field value %08xh.\n", dbgStat, FieldName, StructType, BAD_VALUE);
  292. dprintf(g_genericErrorHelpStr);
  293. result = (UCHAR)BAD_VALUE;
  294. }
  295. return result;
  296. }
  297. ULONG64 GetFieldAddr(ULONG64 StructAddr, LPCSTR StructType, LPCSTR FieldName)
  298. {
  299. ULONG64 result;
  300. ULONG offset;
  301. ULONG dbgStat;
  302. dbgStat = GetFieldOffset(StructType, FieldName, &offset);
  303. if (dbgStat == 0){
  304. result = StructAddr+offset;
  305. }
  306. else {
  307. dprintf("\n GetFieldAddr: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s'.\n", dbgStat, StructType, FieldName);
  308. dprintf(g_genericErrorHelpStr);
  309. result = BAD_VALUE;
  310. }
  311. return result;
  312. }
  313. ULONG64 GetContainingRecord(ULONG64 FieldAddr, LPCSTR StructType, LPCSTR FieldName)
  314. {
  315. ULONG64 result;
  316. ULONG offset;
  317. ULONG dbgStat;
  318. dbgStat = GetFieldOffset(StructType, FieldName, &offset);
  319. if (dbgStat == 0){
  320. result = FieldAddr-offset;
  321. }
  322. else {
  323. dprintf("\n GetContainingRecord: GetFieldOffset failed with %xh retrieving offset of struct '%s' field '%s', returning bogus address %08xh.\n", dbgStat, StructType, FieldName, BAD_VALUE);
  324. dprintf(g_genericErrorHelpStr);
  325. result = BAD_VALUE;
  326. }
  327. return result;
  328. }