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.

607 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. partition.c
  5. Abstract:
  6. Debugger extension for dumping partition structures:
  7. DRIVE_LAYOUT_INFORMATION
  8. DRIVE_LAYOUT_INFORMATION_EX
  9. PARTITION_INFORMATION
  10. PARTITION_INFORMATION_EX
  11. Author:
  12. Matthew D Hendel (math) 19-Jan-2000
  13. Revision History:
  14. --*/
  15. #include "pch.h"
  16. #include <ntdddisk.h>
  17. VOID
  18. DumpPartition(
  19. IN ULONG64 Address,
  20. IN ULONG Detail,
  21. IN ULONG Depth,
  22. IN ULONG PartitionCount
  23. )
  24. /*++
  25. Routine Description:
  26. Dump a PARTITION_INFORMATION structure.
  27. Arguments:
  28. Address - The address of the partition information structure to dump.
  29. Detail - The detail level. Currently unused.
  30. Depth - The depth to indent to.
  31. PartitionCount - The number of partitions. This is used to determine
  32. whether a particular partition ordinal is valid or not.
  33. Return Value:
  34. None.
  35. --*/
  36. {
  37. BOOL Succ;
  38. ULONG Size;
  39. ULONG64 StartingOffset;
  40. ULONG64 PartitionLength;
  41. ULONG PartitionNumber;
  42. UCHAR PartitionType;
  43. BOOLEAN BootIndicator;
  44. BOOLEAN RecognizedPartition;
  45. BOOLEAN RewritePartition;
  46. InitTypeRead(Address, nt!PARTITION_INFORMATION);
  47. StartingOffset = ReadField(StartingOffset.QuadPart);
  48. PartitionLength = ReadField(PartitionLength.QuadPart);
  49. PartitionType = (UCHAR) ReadField(PartitionType);
  50. BootIndicator = (BOOLEAN) ReadField(BootIndicator);
  51. RecognizedPartition = (BOOLEAN) ReadField(RecognizedPartition);
  52. RewritePartition = (BOOLEAN) ReadField(RewritePartition);
  53. PartitionNumber = (ULONG) ReadField(PartitionNumber);
  54. //
  55. // Sanity check the data.
  56. //
  57. if ( (BootIndicator != TRUE && BootIndicator != FALSE) ||
  58. (RecognizedPartition != TRUE && RecognizedPartition != FALSE) ||
  59. (RewritePartition != TRUE && RewritePartition != FALSE) ) {
  60. xdprintfEx (Depth, ("Invalid partition information at %p\n", Address));
  61. }
  62. if (PartitionNumber > PartitionCount) {
  63. PartitionNumber = (ULONG)-1;
  64. }
  65. xdprintfEx (Depth, ("[%-2d] %-16I64x %-16I64x %2.2x %c %c %c\n",
  66. PartitionNumber,
  67. StartingOffset,
  68. PartitionLength,
  69. PartitionType,
  70. BootIndicator ? 'x' : ' ',
  71. RecognizedPartition ? 'x' : ' ',
  72. RewritePartition ? 'x' : ' '
  73. ));
  74. }
  75. VOID
  76. DumpDriveLayout(
  77. IN ULONG64 Address,
  78. IN ULONG Detail,
  79. IN ULONG Depth
  80. )
  81. {
  82. BOOL Succ;
  83. ULONG Size;
  84. ULONG i;
  85. ULONG64 PartAddress;
  86. ULONG result;
  87. ULONG offset;
  88. ULONG PartitionCount;
  89. ULONG Signature;
  90. ULONG OffsetOfFirstPartitionInfo;
  91. ULONG SizeOfPartitionInfo;
  92. InitTypeRead(Address, nt!_DRIVE_LAYOUT_INFORMATION);
  93. PartitionCount = (ULONG) ReadField(PartitionCount);
  94. Signature = (ULONG) ReadField(Signature);
  95. xdprintfEx (Depth, ("\nDRIVE_LAYOUT %p\n", Address));
  96. //
  97. // Warn if the partition count is not a factor of 4. This is probably a
  98. // bad partition information structure, but we'll continue on anyway.
  99. //
  100. if (PartitionCount % 4 != 0) {
  101. xdprintfEx (Depth, ("WARNING: Partition count should be a factor of 4.\n"));
  102. }
  103. xdprintfEx (Depth, ("PartitionCount: %d\n", PartitionCount));
  104. xdprintfEx (Depth, ("Signature: %8.8x\n\n", Signature));
  105. xdprintfEx (Depth+1, (" ORD Offset Length Type BI RP RW\n"));
  106. xdprintfEx (Depth+1, ("------------------------------------------------------------\n"));
  107. result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION",
  108. "PartitionEntry[0]",
  109. &offset);
  110. if (result) {
  111. SCSIKD_PRINT_ERROR(result);
  112. return;
  113. }
  114. OffsetOfFirstPartitionInfo = offset;
  115. result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION",
  116. "PartitionEntry[1]",
  117. &offset);
  118. if (result) {
  119. SCSIKD_PRINT_ERROR(result);
  120. return;
  121. }
  122. SizeOfPartitionInfo = offset - OffsetOfFirstPartitionInfo;
  123. PartAddress = Address + OffsetOfFirstPartitionInfo;
  124. for (i = 0; i < PartitionCount; i++) {
  125. if (CheckControlC()) {
  126. return;
  127. }
  128. DumpPartition(PartAddress, Detail, Depth+1, PartitionCount);
  129. PartAddress += SizeOfPartitionInfo;
  130. }
  131. }
  132. VOID
  133. DumpPartitionEx(
  134. IN ULONG64 Address,
  135. IN ULONG Detail,
  136. IN ULONG Depth,
  137. IN ULONG PartitionCount
  138. )
  139. /*++
  140. Routine Description:
  141. Dump a PARTITION_INFORMATION_EX structure.
  142. Arguments:
  143. Address - The address of the partition information structure to dump.
  144. Detail - The detail level. Currently unused.
  145. Depth - The depth to indent to.
  146. PartitionCount - The number of partitions. This is used to determine
  147. whether a particular partition ordinal is valid or not.
  148. Return Value:
  149. None.
  150. --*/
  151. {
  152. BOOL Succ;
  153. ULONG Size;
  154. ULONG result;
  155. ULONG offset;
  156. ULONG PartitionStyle;
  157. ULONG PartitionNumber;
  158. ULONG64 StartingOffset;
  159. ULONG64 PartitionLength;
  160. BOOLEAN RewritePartition;
  161. UCHAR MbrPartitionType;
  162. BOOLEAN MbrBootIndicator;
  163. BOOLEAN MbrRecognizedPartition;
  164. ULONG64 GptAttributes;
  165. GUID GptPartitionType;
  166. GUID GptPartitionId;
  167. ULONG64 AddrOfGuid;
  168. WCHAR GptName[36];
  169. InitTypeRead (Address, nt!_PARTITION_INFORMATION_EX);
  170. PartitionStyle = (ULONG) ReadField(PartitionStyle);
  171. if (PartitionStyle != PARTITION_STYLE_MBR &&
  172. PartitionStyle != PARTITION_STYLE_GPT) {
  173. SCSIKD_PRINT_ERROR(0);
  174. return;
  175. }
  176. PartitionNumber = (ULONG) ReadField(PartitionNumber);
  177. StartingOffset = ReadField(StartingOffset.QuadPart);
  178. PartitionLength = ReadField(PartitionLength.QuadPart);
  179. RewritePartition = (BOOLEAN) ReadField(RewritePartition);
  180. //
  181. // We use -1 to denote an invalid partition ordinal.
  182. //
  183. if (PartitionNumber >= PartitionCount) {
  184. PartitionNumber = (ULONG)-1;
  185. }
  186. InitTypeRead (Address, nt!_PARTITION_INFORMATION_EX);
  187. if (PartitionStyle == PARTITION_STYLE_MBR) {
  188. MbrPartitionType = (UCHAR) ReadField(Mbr.PartitionType);
  189. MbrBootIndicator = (BOOLEAN) ReadField(Mbr.BootIndicator);
  190. MbrRecognizedPartition = (BOOLEAN) ReadField(Mbr.RecognizedPartition);
  191. xdprintfEx (Depth, ("[%-2d] %-16I64x %-16I64x %2.2x %c %c %c\n",
  192. PartitionNumber,
  193. StartingOffset,
  194. PartitionLength,
  195. MbrPartitionType,
  196. MbrBootIndicator ? 'x' : ' ',
  197. MbrRecognizedPartition ? 'x' : ' ',
  198. RewritePartition ? 'x' : ' '
  199. ));
  200. } else {
  201. GptAttributes = ReadField(Gpt.Attributes);
  202. result = GetFieldOffset("nt!_PARTITION_INFORMATION_EX",
  203. "Gpt.PartitionType",
  204. &offset);
  205. if (result) {
  206. SCSIKD_PRINT_ERROR(result);
  207. return;
  208. }
  209. AddrOfGuid = Address + offset;
  210. Succ = ReadMemory (
  211. AddrOfGuid,
  212. &GptPartitionType,
  213. sizeof (GUID),
  214. &Size
  215. );
  216. if (!Succ || Size != sizeof (GUID)) {
  217. SCSIKD_PRINT_ERROR(0);
  218. return;
  219. }
  220. //
  221. // PartitionId immediately follows the PartitionType. So all we have to do
  222. // is add sizeof(GUID) to the address and read PartitionId.
  223. //
  224. AddrOfGuid += sizeof(GUID);
  225. Succ = ReadMemory (
  226. AddrOfGuid,
  227. &GptPartitionId,
  228. sizeof (GUID),
  229. &Size
  230. );
  231. if (!Succ || Size != sizeof (GUID)) {
  232. SCSIKD_PRINT_ERROR(0);
  233. return;
  234. }
  235. //
  236. // Read in the Gpt.Name.
  237. //
  238. result = GetFieldOffset("nt!_PARTITION_INFORMATION_EX",
  239. "Gpt.Name",
  240. &offset);
  241. if (result) {
  242. SCSIKD_PRINT_ERROR(result);
  243. return;
  244. }
  245. Succ = ReadMemory (
  246. Address + offset,
  247. &GptName,
  248. sizeof (WCHAR) * 36,
  249. &Size
  250. );
  251. if (!Succ || Size != sizeof (GUID)) {
  252. SCSIKD_PRINT_ERROR(0);
  253. return;
  254. }
  255. xdprintfEx (Depth, ("[%-2d] %S\n",
  256. PartitionNumber, GptName));
  257. xdprintfEx (Depth, ("OFF %-16I64x LEN %-16I64x ATTR %-16I64x R/W %c\n",
  258. StartingOffset,
  259. PartitionLength,
  260. GptAttributes,
  261. RewritePartition ? 'T' : 'F'));
  262. xdprintfEx (Depth, ("TYPE %s\n",
  263. GuidToString (&GptPartitionType)));
  264. xdprintfEx (Depth, ("ID %s\n",
  265. GuidToString (&GptPartitionId)));
  266. xdprintfEx (Depth, ("\n"));
  267. }
  268. }
  269. VOID
  270. DumpDriveLayoutEx(
  271. IN ULONG64 Address,
  272. IN ULONG Detail,
  273. IN ULONG Depth
  274. )
  275. {
  276. ULONG result;
  277. BOOL Succ;
  278. ULONG Size;
  279. ULONG i;
  280. ULONG offset;
  281. ULONG64 AddrOfDiskId;
  282. ULONG PartitionStyle;
  283. ULONG PartitionCount;
  284. ULONG MbrSignature;
  285. GUID GptDiskId;
  286. ULONG64 GptStartingUsableOffset;
  287. ULONG64 GptUsableLength;
  288. ULONG GptMaxPartitionCount;
  289. ULONG SizeOfPartitionEntry;
  290. ULONG OffsetOfFirstPartitionEntry;
  291. InitTypeRead(Address, nt!_DRIVE_LAYOUT_INFORMATION_EX);
  292. PartitionStyle = (ULONG)ReadField(PartitionStyle);
  293. PartitionCount = (ULONG)ReadField(PartitionCount);
  294. MbrSignature = (ULONG)ReadField(Mbr.Signature);
  295. GptStartingUsableOffset = ReadField(Gpt.StartingUsableOffset.QuadPart);
  296. GptUsableLength = ReadField(Gpt.UsableLength.QuadPart);
  297. GptMaxPartitionCount = (ULONG)ReadField(Gpt.MaxPartitionCount);
  298. result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
  299. "Gpt.DiskId",
  300. &offset);
  301. if (result) {
  302. SCSIKD_PRINT_ERROR(result);
  303. return;
  304. }
  305. AddrOfDiskId = Address + offset;
  306. Succ = ReadMemory(
  307. AddrOfDiskId,
  308. &GptDiskId,
  309. sizeof(GUID),
  310. &Size);
  311. if (!Succ || Size != sizeof(GUID)) {
  312. SCSIKD_PRINT_ERROR(result);
  313. return;
  314. }
  315. xdprintfEx (Depth, ("\nDRIVE_LAYOUT_EX %p\n", Address));
  316. if (PartitionStyle != PARTITION_STYLE_MBR &&
  317. PartitionStyle != PARTITION_STYLE_GPT) {
  318. xdprintfEx (Depth, ("ERROR: invalid partition style %d\n", PartitionStyle));
  319. return;
  320. }
  321. if (PartitionStyle == PARTITION_STYLE_MBR &&
  322. PartitionCount % 4 != 0) {
  323. xdprintfEx (Depth, ("WARNING: Partition count is not a factor of 4, (%d)\n",
  324. PartitionCount));
  325. }
  326. if (PartitionStyle == PARTITION_STYLE_MBR) {
  327. xdprintfEx (Depth, ("Signature: %8.8x\n", MbrSignature));
  328. xdprintfEx (Depth, ("PartitionCount %d\n\n", PartitionCount));
  329. xdprintfEx (Depth+1, (" ORD Offset Length Type BI RP RW\n"));
  330. xdprintfEx (Depth+1, ("------------------------------------------------------------\n"));
  331. } else {
  332. xdprintfEx (Depth, ("DiskId: %s\n", GuidToString (&GptDiskId)));
  333. xdprintfEx (Depth, ("StartingUsableOffset: %I64x\n", GptStartingUsableOffset));
  334. xdprintfEx (Depth, ("UsableLength: %I64x\n", GptUsableLength));
  335. xdprintfEx (Depth, ("MaxPartitionCount: %d\n", GptMaxPartitionCount));
  336. xdprintfEx (Depth, ("PartitionCount %d\n\n", PartitionCount));
  337. }
  338. result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
  339. "PartitionEntry[i]",
  340. &offset);
  341. if (result) {
  342. SCSIKD_PRINT_ERROR(result);
  343. return;
  344. }
  345. OffsetOfFirstPartitionEntry = offset;
  346. Address += offset;
  347. result = GetFieldOffset("nt!_DRIVE_LAYOUT_INFORMATION_EX",
  348. "PartitionEntry[1]",
  349. &offset);
  350. if (result) {
  351. SCSIKD_PRINT_ERROR(result);
  352. return;
  353. }
  354. SizeOfPartitionEntry = offset - OffsetOfFirstPartitionEntry;
  355. for (i = 0; i < PartitionCount; i++) {
  356. if (CheckControlC()) {
  357. return;
  358. }
  359. DumpPartitionEx(Address, Detail, Depth+1, PartitionCount);
  360. Address += SizeOfPartitionEntry;
  361. }
  362. }
  363. DECLARE_API (layout)
  364. /*++
  365. Routine Description:
  366. Dump a DRIVE_LAYOUT structure with all it's partitions.
  367. Arguments:
  368. args - A string containing the address of the DRIVE_LAYOUT structure to
  369. be dumped.
  370. Return Value:
  371. None.
  372. --*/
  373. {
  374. ULONG64 Address;
  375. ULONG Detail = 0;
  376. GetAddressAndDetailLevel64 (args, &Address, &Detail);
  377. DumpDriveLayout (Address, Detail, 0);
  378. return S_OK;
  379. }
  380. DECLARE_API (layoutex)
  381. /*++
  382. Routine Description:
  383. Dump a DRIVE_LAYOUT_EX structure and it's partitions.
  384. Usage:
  385. layoutex <address>
  386. Arguments:
  387. args - A string containing the address of the DRIVE_LAYOUT_EX structure
  388. to be dumped.
  389. Return Value:
  390. None.
  391. --*/
  392. {
  393. ULONG64 Address;
  394. ULONG Detail = 0;
  395. GetAddressAndDetailLevel64 (args, &Address, &Detail);
  396. DumpDriveLayoutEx (Address, Detail, 0);
  397. return S_OK;
  398. }
  399. DECLARE_API (part)
  400. /*++
  401. Routine Description:
  402. Dump a PARTITION_INFORMATION structure.
  403. Usage:
  404. part <address>
  405. Arguments:
  406. args - A string containing the address of the PARTITION_INFORMATION
  407. structure to be dumped.
  408. Return Value:
  409. None.
  410. --*/
  411. {
  412. ULONG64 Address;
  413. ULONG Detail = 0;
  414. GetAddressAndDetailLevel64 (args, &Address, &Detail);
  415. DumpPartition (Address, Detail, 0, 0);
  416. return S_OK;
  417. }
  418. DECLARE_API (partex)
  419. /*++
  420. Routine Description:
  421. Dump a PARTITION_INFORMATION_EX structure.
  422. Usage:
  423. partex <address>
  424. Arguments:
  425. args - A string containing the address of the PARTITION_INFORMATION_EX
  426. structure to be dumped.
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. ULONG64 Address;
  432. ULONG Detail = 0;
  433. GetAddressAndDetailLevel64 (args, &Address, &Detail);
  434. DumpPartitionEx (Address, Detail, 0, 0);
  435. return S_OK;
  436. }