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.

1387 lines
33 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. redbook.c
  5. Abstract:
  6. Debugger Extension Api for interpretting scsiport structures
  7. Author:
  8. Henry Gabryjelski 23-Oct-1998
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #define INDENT 2
  15. //#define PRINT_LINE() dprintf("Line %4d File %s\n", __LINE__, __FILE__)
  16. #define DUMP_STRUCT(v,d,x,y) \
  17. if ((v) <= Detail) { xdprintf( (d), "%-20s - %#010x\n", (x), (y) ); }
  18. #define DUMP_STRUCT_P(v,d,x,y) \
  19. if ((v) <= Detail) { xdprintf( (d), "%-20s - %#p\n", (x), (y) ); }
  20. #define DUMP_STRUCT64(v,d,x,y) \
  21. if ((v) <= Detail) { xdprintf( (d), "%-20s - %#016I64x\n", (x), (y) ); }
  22. #define PRINT_FLAGS(Flags,b) \
  23. if (Flags & b) { dprintf( #b ", " ); }
  24. typedef struct _FLAG_NAME {
  25. ULONG Flag;
  26. PUCHAR Name;
  27. } FLAG_NAME, *PFLAG_NAME;
  28. #define FLAG_NAME(flag) {flag, #flag}
  29. FLAG_NAME CdFlags[] = {
  30. FLAG_NAME(CD_STOPPED), // 0000 0001
  31. FLAG_NAME(CD_PAUSED), // 0000 0002
  32. FLAG_NAME(CD_PLAYING), // 0000 0004
  33. FLAG_NAME(CD_STOPPING), // 0000 0010
  34. FLAG_NAME(CD_PAUSING), // 0000 0020
  35. {0,0}
  36. };
  37. PUCHAR const REDBOOK_CC_STRINGS[5] = {
  38. " Read ",
  39. " Stream ",
  40. " Read Com ",
  41. "Stream Com",
  42. "*Unknown* "
  43. };
  44. VOID
  45. DumpToc(
  46. IN PVOID X,
  47. IN ULONG_PTR Address,
  48. IN ULONG Detail,
  49. IN LONG Depth
  50. );
  51. VOID
  52. DumpContext(
  53. IN PVOID X,
  54. IN ULONG_PTR Address,
  55. IN ULONG Detail,
  56. IN LONG Depth
  57. );
  58. VOID
  59. DumpFlags(
  60. LONG Depth,
  61. PUCHAR Name,
  62. ULONG Flags,
  63. PFLAG_NAME FlagTable
  64. );
  65. VOID
  66. DumpList(
  67. PVOID AddressOfListHead
  68. );
  69. VOID
  70. DumpRedBookBufferData(
  71. IN PVOID X,
  72. IN ULONG_PTR Address,
  73. IN ULONG Detail,
  74. IN LONG Depth
  75. );
  76. VOID
  77. DumpRedBookCdromInfo(
  78. IN PVOID X,
  79. IN ULONG_PTR Address,
  80. IN ULONG Detail,
  81. IN LONG Depth
  82. );
  83. VOID
  84. DumpRedBookExtension(
  85. IN PVOID X,
  86. IN ULONG_PTR Address,
  87. IN ULONG Detail,
  88. IN LONG Depth
  89. );
  90. VOID
  91. DumpRedBookStreamData(
  92. IN PVOID X,
  93. IN ULONG_PTR Address,
  94. IN ULONG Detail,
  95. IN LONG Depth
  96. );
  97. VOID
  98. DumpRedBookThreadData(
  99. IN PVOID X,
  100. IN ULONG_PTR Address,
  101. IN ULONG Detail,
  102. IN LONG Depth
  103. );
  104. VOID
  105. DumpRedBookWmiData(
  106. IN PVOID X,
  107. IN ULONG_PTR Address,
  108. IN ULONG Detail,
  109. IN LONG Depth
  110. );
  111. VOID
  112. DumpRedBookWmiPerf(
  113. IN PVOID X,
  114. IN ULONG_PTR Address,
  115. IN ULONG Detail,
  116. IN LONG Depth
  117. );
  118. VOID
  119. GetPointer(
  120. IN ULONG_PTR Address,
  121. OUT ULONG_PTR *Value
  122. );
  123. VOID
  124. GetAddressAndDetailLevelFromArgs(
  125. PCSTR Args,
  126. PULONG_PTR Address,
  127. PULONG Detail
  128. );
  129. VOID
  130. ParseArguments(
  131. PCSTR Args,
  132. PULONG_PTR Address,
  133. PULONG Detail,
  134. PVOID Block
  135. );
  136. VOID
  137. xdprintf(
  138. LONG Depth,
  139. PCCHAR S,
  140. ...
  141. );
  142. ////////////////////////////////////////////////////////////////////////////////
  143. DECLARE_API(ext)
  144. /*++
  145. Routine Description:
  146. Dumps the device extension for a given device object, or dumps the
  147. given device extension
  148. --*/
  149. {
  150. ULONG_PTR address;
  151. ULONG detail = 0;
  152. UCHAR block[sizeof(REDBOOK_DEVICE_EXTENSION)];
  153. PUCHAR blah;
  154. ParseArguments(args, &address, &detail, block);
  155. if (address == 0) {
  156. return;
  157. }
  158. blah = block; // no field offset
  159. // address = FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, .);
  160. DumpRedBookExtension(block, address, detail, 0);
  161. return;
  162. }
  163. DECLARE_API(toc)
  164. /*++
  165. Routine Description:
  166. Dumps the device extension for a given device object, or dumps the
  167. given device extension
  168. --*/
  169. {
  170. ULONG_PTR address;
  171. ULONG detail = 0;
  172. UCHAR block[sizeof(CDROM_TOC)];
  173. ULONG result;
  174. GetAddressAndDetailLevelFromArgs(args, &address, &detail);
  175. if (address == 0) {
  176. return;
  177. }
  178. if(!ReadMemory(address, block, sizeof(CDROM_TOC), &result)) {
  179. xdprintf(0, "Error reading CDROM_TOC at address %p\n", address);
  180. return;
  181. }
  182. DumpToc(block, address, detail, 0);
  183. return;
  184. }
  185. DECLARE_API(context)
  186. /*++
  187. Routine Description:
  188. Dumps the device extension for a given device object, or dumps the
  189. given device extension
  190. --*/
  191. {
  192. ULONG_PTR address;
  193. ULONG detail = 0;
  194. UCHAR block[sizeof(REDBOOK_COMPLETION_CONTEXT)];
  195. ULONG result;
  196. GetAddressAndDetailLevelFromArgs(args, &address, &detail);
  197. if (address == 0) {
  198. return;
  199. }
  200. if(!ReadMemory(address, block, sizeof(REDBOOK_COMPLETION_CONTEXT), &result)) {
  201. xdprintf(0, "Error reading CDROM_TOC at address %p\n", address);
  202. return;
  203. }
  204. DumpContext(block, address, detail, 0);
  205. return;
  206. }
  207. DECLARE_API(silence)
  208. {
  209. ULONG_PTR silenceAddress;
  210. ULONG silence;
  211. ULONG result;
  212. UCHAR * silenceString = "redbook!RedBookForceSilence";
  213. silenceAddress = (ULONG_PTR) GetExpression(silenceString);
  214. if (!silenceAddress) {
  215. dprintf(
  216. "Unable to get address of %s\n"
  217. "It could be that redbook is not loaded,"
  218. "was build FRE, or the symbols are wrong\n",
  219. silenceString
  220. );
  221. return;
  222. }
  223. if (!ReadMemory(silenceAddress, &silence, sizeof(ULONG), &result)) {
  224. dprintf("Unable to read current value for silence (%p)!\n",
  225. silenceAddress);
  226. return;
  227. }
  228. //
  229. // allow them to provide an argument?
  230. //
  231. if (args[0]) {
  232. silence = (ULONG) GetExpression(args);
  233. dprintf("Setting ForceSilence %s\n", (silence?"on":"off"));
  234. } else {
  235. dprintf("Toggling ForceSilence from %s to %s\n",
  236. (silence?"on":"off"),
  237. (silence?"off":"on"));
  238. silence = (silence?0:1);
  239. }
  240. if(!WriteMemory(silenceAddress, &silence, sizeof(ULONG), &result)) {
  241. dprintf("Unable to set ForceSilence %s\n", (silence?"on":"off"));
  242. return;
  243. }
  244. return;
  245. }
  246. DECLARE_API(wmiperfclear)
  247. {
  248. ULONG_PTR address;
  249. ULONG detail = 0;
  250. ULONG result;
  251. UCHAR block[sizeof(REDBOOK_DEVICE_EXTENSION)];
  252. PREDBOOK_DEVICE_EXTENSION deviceExtension;
  253. ParseArguments(args, &address, &detail, block);
  254. if (address == 0) {
  255. return;
  256. }
  257. deviceExtension = (PREDBOOK_DEVICE_EXTENSION)block;
  258. deviceExtension->WmiPerf.TimeReadDelay = 0;
  259. deviceExtension->WmiPerf.TimeReading = 0;
  260. deviceExtension->WmiPerf.TimeStreamDelay = 0;
  261. deviceExtension->WmiPerf.TimeStreaming = 0;
  262. deviceExtension->WmiPerf.DataProcessed = 0;
  263. deviceExtension->WmiPerf.StreamPausedCount = 0;
  264. if(!WriteMemory(address, (PVOID)block, sizeof(REDBOOK_DEVICE_EXTENSION), &result)) {
  265. xdprintf(0, "Error writing redbook wmi data to address %p\n", address);
  266. return;
  267. }
  268. return;
  269. }
  270. ////////////////////////////////////////////////////////////////////////////////
  271. PUCHAR ErrorText[REDBOOK_ERR_MAXIMUM] = {
  272. "Errors Reading Raw Audio",
  273. "Errors Streaming Raw Audio",
  274. "Errors opening SysAudio Mixer",
  275. "Errors creating virtual source",
  276. "Errors opening preferred waveout device",
  277. "Errors getting number of pins on waveout device",
  278. "Errors connecting to playback pins on waveout device",
  279. "Errors initializing WMI",
  280. "Errors creating thread",
  281. "Warning due to insufficient data (stream paused)",
  282. "This is an unsupported drive"
  283. };
  284. VOID
  285. DumpRedBookErrors(
  286. IN PVOID X,
  287. IN ULONG_PTR Address,
  288. IN ULONG Detail,
  289. IN LONG Depth
  290. )
  291. {
  292. PREDBOOK_DEVICE_EXTENSION DeviceExtension = X;
  293. ULONG_PTR errorCountAddress;
  294. ULONG tmp;
  295. ULONG errors[REDBOOK_ERR_MAXIMUM];
  296. Depth += INDENT;
  297. errorCountAddress =
  298. (ULONG_PTR)((PUCHAR)Address +
  299. FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, ErrorLog.RCount[0]));
  300. xdprintf(Depth, "%x Errors Reported. Error Counts at %p\n",
  301. DeviceExtension->ErrorLog.Count, errorCountAddress);
  302. if (!ReadMemory(errorCountAddress, &errors,
  303. sizeof(ULONG) * REDBOOK_ERR_MAXIMUM, &tmp)) {
  304. xdprintf(Depth, "Unable to read error information\n");
  305. return;
  306. }
  307. Depth += INDENT;
  308. for (tmp = 0; tmp < REDBOOK_ERR_MAXIMUM; tmp++) {
  309. if (errors[tmp] != 0) {
  310. xdprintf(Depth, "%2x - %s\n", errors[tmp], ErrorText[tmp]);
  311. }
  312. }
  313. Depth -= INDENT;
  314. }
  315. ////////////////////////////////////////////////////////////////////////////////
  316. VOID
  317. DumpRedBookExtension(
  318. IN PVOID X,
  319. IN ULONG_PTR Address,
  320. IN ULONG Detail,
  321. IN LONG Depth
  322. )
  323. {
  324. PREDBOOK_DEVICE_EXTENSION DeviceExtension = X;
  325. Depth += INDENT;
  326. dprintf("\n");
  327. xdprintf(Depth, "Device Extension at %p\n", Address);
  328. xdprintf(Depth, "TargetDevObj %p TargetPdo %p SelfDevObj %p\n",
  329. DeviceExtension->TargetDeviceObject,
  330. DeviceExtension->TargetPdo,
  331. DeviceExtension->SelfDeviceObject);
  332. xdprintf(Depth, "PNP: CurrentState %x PreviousState %x\n",
  333. DeviceExtension->Pnp.CurrentState,
  334. DeviceExtension->Pnp.PreviousState);
  335. xdprintf(Depth, " RemovePending %x IoRemoveLock %p\n",
  336. DeviceExtension->Pnp.RemovePending,
  337. Address+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, RemoveLock));
  338. xdprintf(Depth, "WmiLibInfo: %p (%x bytes) Paging Path Count: %x\n",
  339. Address+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION, WmiLibInfo),
  340. sizeof(WMILIB_CONTEXT),
  341. DeviceExtension->PagingPathCount);
  342. dprintf("\n");
  343. DumpRedBookErrors(X, Address, Detail, Depth);
  344. DumpRedBookCdromInfo((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,CDRom),
  345. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,CDRom),
  346. Detail,
  347. Depth
  348. );
  349. DumpRedBookStreamData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Stream),
  350. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Stream),
  351. Detail,
  352. Depth
  353. );
  354. DumpRedBookThreadData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Thread),
  355. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Thread),
  356. Detail,
  357. Depth
  358. );
  359. DumpRedBookWmiData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiData),
  360. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiData),
  361. Detail,
  362. Depth
  363. );
  364. DumpRedBookWmiPerf((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiPerf),
  365. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,WmiPerf),
  366. Detail,
  367. Depth
  368. );
  369. DumpRedBookBufferData((PUCHAR)X+FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Buffer),
  370. Address +FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,Buffer),
  371. Detail,
  372. Depth
  373. );
  374. if (Detail) {
  375. ULONG Index;
  376. ULONG i;
  377. PUCHAR savedIo;
  378. Index = DeviceExtension->SavedIoCurrentIndex + (SAVED_IO_MAX - 1);
  379. Index %= SAVED_IO_MAX;
  380. savedIo = (PUCHAR)Address;
  381. savedIo += FIELD_OFFSET(REDBOOK_DEVICE_EXTENSION,SavedIo[0].IrpWithoutStack);
  382. xdprintf(Depth, "Irp History: \n");
  383. for (i=0; i < SAVED_IO_MAX; i++) {
  384. ULONG realIndex;
  385. realIndex = Index + i;
  386. realIndex %= SAVED_IO_MAX;
  387. xdprintf(Depth, "Irp %p: !irp %p\n",
  388. DeviceExtension->SavedIo[realIndex].OriginalIrp,
  389. savedIo + (sizeof(SAVED_IO) * realIndex)
  390. );
  391. }
  392. }
  393. dprintf("\n");
  394. return;
  395. }
  396. VOID
  397. DumpRedBookCdromInfo(
  398. IN PVOID X,
  399. IN ULONG_PTR Address,
  400. IN ULONG Detail,
  401. IN LONG Depth
  402. )
  403. {
  404. PREDBOOK_CDROM_INFO Cdrom = X;
  405. xdprintf(Depth, "CDROM INFO at %p\n", Address);
  406. Depth += INDENT;
  407. xdprintf(Depth, "CachedToc %p MediaChangeCount %x\n",
  408. Cdrom->Toc,
  409. Cdrom->CheckVerify);
  410. DumpFlags(Depth, "CdState", Cdrom->StateNow, CdFlags);
  411. xdprintf(Depth, "Sector information:\n");
  412. xdprintf(Depth, "NextToRead %x NextToStream %x FinishedStreaming %x\n",
  413. Cdrom->NextToRead,
  414. Cdrom->NextToStream,
  415. Cdrom->FinishedStreaming);
  416. xdprintf(Depth, "EndPlay %x ReadErrors %x StreamErrors %x\n",
  417. Cdrom->EndPlay,
  418. Cdrom->ReadErrors,
  419. Cdrom->StreamErrors);
  420. xdprintf(Depth, "Volume for ports 0-3: %x %x %x %x\n",
  421. Cdrom->Volume.PortVolume[0],
  422. Cdrom->Volume.PortVolume[1],
  423. Cdrom->Volume.PortVolume[2],
  424. Cdrom->Volume.PortVolume[3]);
  425. Depth -= INDENT;
  426. return;
  427. }
  428. VOID
  429. DumpRedBookWmiData(
  430. IN PVOID X,
  431. IN ULONG_PTR Address,
  432. IN ULONG Detail,
  433. IN LONG Depth
  434. )
  435. {
  436. PREDBOOK_WMI_STD_DATA WmiData = X;
  437. xdprintf(Depth, "WMIDATA at %p\n", Address);
  438. Depth += INDENT;
  439. xdprintf(Depth, "Number of buffers: %x\n",
  440. WmiData->NumberOfBuffers
  441. );
  442. xdprintf(Depth, "Sectors: Per Read %x Mask %x Maximum\n",
  443. WmiData->SectorsPerRead,
  444. WmiData->SectorsPerReadMask,
  445. WmiData->MaximumSectorsPerRead
  446. );
  447. xdprintf(Depth, "Enabled %x CDDASupported %x CDDAAccurate %x\n",
  448. WmiData->PlayEnabled,
  449. WmiData->CDDASupported,
  450. WmiData->CDDAAccurate
  451. );
  452. Depth -= INDENT;
  453. return;
  454. }
  455. VOID
  456. DumpRedBookWmiPerf(
  457. IN PVOID X,
  458. IN ULONG_PTR Address,
  459. IN ULONG Detail,
  460. IN LONG Depth
  461. )
  462. {
  463. PREDBOOK_WMI_PERF_DATA WmiPerf = X;
  464. xdprintf(Depth, "WMIPERF at %p\n", Address);
  465. //
  466. // problems printing the info below.
  467. // it actually crashes the debugger.
  468. //
  469. Depth += INDENT;
  470. xdprintf(Depth, "ReadDelay %I64x Reading %I64x\n",
  471. WmiPerf->TimeReadDelay,
  472. WmiPerf->TimeReading
  473. );
  474. xdprintf(Depth, "StreamDelay %I64x Streaming %I64x\n",
  475. WmiPerf->TimeStreamDelay,
  476. WmiPerf->TimeStreaming
  477. );
  478. xdprintf(Depth, "DataProcessed %I64x StreamPausedCount %x\n",
  479. WmiPerf->DataProcessed,
  480. WmiPerf->StreamPausedCount
  481. );
  482. return;
  483. #if 0
  484. if (WmiPerf->DataRead != 0) {
  485. xdprintf( Depth, "\n" );
  486. xdprintf( Depth, " stat seconds\n" );
  487. xdprintf( Depth, "------------- -----------------------------\n" );
  488. #define TIME_FORMAT_STRINGa "%12s: %7I64d.%-02I64d\n"
  489. #define TIME_FORMAT_STRING "%12s: %7I64d.%-07I64d\n"
  490. #define UNITS_PER_SECOND ((LONG64)10000000)
  491. xdprintf( Depth, TIME_FORMAT_STRINGa,
  492. "audio data",
  493. WmiPerf->DataRead / (RAW_SECTOR_SIZE * 75),
  494. (WmiPerf->DataRead / RAW_SECTOR_SIZE) % 75
  495. );
  496. //
  497. // what is the approximate transfer speed of the drive?
  498. // in kb/s, but actually calculated as b/(s / 1024^2)
  499. //
  500. tempStat = WmiPerf->DataRead / 0x00000400; // kb
  501. xdprintf( Depth, " Kbytes read: %I64d\n", tempStat );
  502. xdprintf( Depth, " seconds: %I64d . %I64d\n",
  503. WmiPerf->TimeReading / UNITS_PER_SECOND,
  504. WmiPerf->TimeReading % UNITS_PER_SECOND
  505. );
  506. //
  507. // need to keep the numbers large, so:
  508. //
  509. tempStat = WmiPerf->TimeReading;
  510. tempStat /= (UNITS_PER_SECOND / 0x00000400);
  511. xdprintf( Depth, " approx drive speed: %I64d kb/s\n",
  512. WmiPerf->DataRead / tempStat );
  513. tempStat = WmiPerf->TimeReading +
  514. WmiPerf->TimeReadDelay +
  515. WmiPerf->TimeStreamDelay;
  516. tempStat /= (UNITS_PER_SECOND / 0x00000400);
  517. xdprintf( Depth, "effective drive speed: %I64d kb/s\n",
  518. WmiPerf->DataRead / tempStat );
  519. /*
  520. tempStat /= WmiPerf->TimeReading / UNITS_PER_SECOND; // per second
  521. xdprintf( Depth, "Approximate drive speed: %I64d kb/s\n", tempStat );
  522. xdprintf( Depth, TIME_FORMAT_STRING
  523. "reading",
  524. WmiPerf->TimeReading / UNITS_PER_SECOND,
  525. WmiPerf->TimeReading % UNITS_PER_SECOND
  526. );
  527. xdprintf( Depth, TIME_FORMAT_STRING
  528. "streaming",
  529. WmiPerf->TimeStreaming / UNITS_PER_SECOND,
  530. WmiPerf->TimeStreaming % UNITS_PER_SECOND
  531. );
  532. xdprintf( Depth, TIME_FORMAT_STRING
  533. "read delay",
  534. WmiPerf->TimeReadDelay / UNITS_PER_SECOND,
  535. WmiPerf->TimeReadDelay % UNITS_PER_SECOND
  536. );
  537. xdprintf( Depth, TIME_FORMAT_STRING
  538. "stream delay",
  539. WmiPerf->TimeStreaming / UNITS_PER_SECOND,
  540. WmiPerf->TimeStreaming % UNITS_PER_SECOND
  541. );
  542. //
  543. // now do some simple analysis, use seconds as unit
  544. //
  545. */
  546. }
  547. Depth -= INDENT;
  548. return;
  549. #endif // 0
  550. }
  551. VOID
  552. DumpRedBookBufferData(
  553. IN PVOID X,
  554. IN ULONG_PTR Address,
  555. IN ULONG Detail,
  556. IN LONG Depth
  557. )
  558. {
  559. PREDBOOK_BUFFER_DATA Buffer = X;
  560. ULONG numBuf;
  561. ULONG sectorsPerRead;
  562. ULONG i;
  563. PULONG readOk_X;
  564. PULONG streamOk_X;
  565. ULONG result;
  566. xdprintf(Depth, "BUFFERS at %p\n", Address);
  567. numBuf = CONTAINING_RECORD(X, REDBOOK_DEVICE_EXTENSION, Buffer)->WmiData.NumberOfBuffers;
  568. sectorsPerRead = CONTAINING_RECORD(X, REDBOOK_DEVICE_EXTENSION, Buffer)->WmiData.SectorsPerRead;
  569. Depth += INDENT;
  570. if (Buffer->ReadOk_X == NULL ||
  571. Buffer->StreamOk_X == NULL ||
  572. Buffer->Contexts == NULL) {
  573. xdprintf(Depth, "One of the pointers is NULL\n");
  574. return;
  575. }
  576. readOk_X = (PULONG)LocalAlloc(LPTR, sizeof(ULONG)*numBuf);
  577. streamOk_X = (PULONG)LocalAlloc(LPTR, sizeof(ULONG)*numBuf);
  578. if (readOk_X == NULL ||
  579. streamOk_X == NULL) {
  580. if (readOk_X) {
  581. LocalFree(readOk_X);
  582. }
  583. if (streamOk_X) {
  584. LocalFree(streamOk_X);
  585. }
  586. xdprintf(Depth, "Can't Alloc Memory\n");
  587. return;
  588. }
  589. if(!ReadMemory((ULONG_PTR)(Buffer->ReadOk_X),
  590. readOk_X,
  591. sizeof(ULONG)*numBuf,
  592. &result)) {
  593. xdprintf(0, "Error reading ReadOk_X\n");
  594. LocalFree(readOk_X);
  595. LocalFree(streamOk_X);
  596. return;
  597. }
  598. if(!ReadMemory((ULONG_PTR)(Buffer->StreamOk_X),
  599. streamOk_X,
  600. sizeof(ULONG)*numBuf,
  601. &result)) {
  602. xdprintf(0, "Error reading StreamOk_X\n");
  603. LocalFree(readOk_X);
  604. LocalFree(streamOk_X);
  605. return;
  606. }
  607. //
  608. // now just parse and print
  609. //
  610. xdprintf(Depth, "SkipBuffer %p to %p (%x bytes)\n",
  611. Buffer->SkipBuffer,
  612. Buffer->SkipBuffer + (RAW_SECTOR_SIZE * sectorsPerRead * numBuf),
  613. RAW_SECTOR_SIZE * sectorsPerRead
  614. );
  615. xdprintf(Depth, "IrpStack %x Stream is %s\n",
  616. Buffer->MaxIrpStack,
  617. (Buffer->Paused ?
  618. (Buffer->FirstPause ? "in its first pause" : "paused")
  619. : "not paused")
  620. );
  621. xdprintf(Depth, "Silent Buffer %p Silent Mdl %p\n",
  622. Buffer->SilentBuffer,
  623. Buffer->SilentMdl
  624. );
  625. dprintf("\n");
  626. xdprintf(Depth, "PRINTING %x BUFFERS (does it match?)\n", numBuf);
  627. xdprintf(Depth, " %8s | %10s | %8s | %8s | %8s | %8s\n",
  628. " Index ",
  629. " Reason ",
  630. " Buffer ",
  631. " Mdl ",
  632. " Irp ",
  633. " R/S OK "
  634. );
  635. xdprintf(Depth, "----------+------------+----------+----------+----------+"
  636. "----------\n");
  637. for (i=0;i<numBuf;i++) {
  638. REDBOOK_COMPLETION_CONTEXT context;
  639. if(!ReadMemory((ULONG_PTR)(Buffer->Contexts+i),
  640. &context,
  641. sizeof(REDBOOK_COMPLETION_CONTEXT),
  642. &result)) {
  643. xdprintf(0, "Error reading CompletionContext at address %p\n",
  644. Buffer->Contexts + i);
  645. } else {
  646. xdprintf(Depth, "");
  647. dprintf(" %8x |",
  648. context.Index);
  649. if (context.Reason > 4) {
  650. dprintf(" %s |", REDBOOK_CC_STRINGS[4]);
  651. } else {
  652. dprintf(" %s |", REDBOOK_CC_STRINGS[context.Reason]);
  653. }
  654. dprintf(" %8p |",
  655. context.Buffer);
  656. dprintf(" %8p |",
  657. context.Mdl);
  658. dprintf(" %8p |",
  659. context.Irp);
  660. dprintf(" %4s\n",
  661. (readOk_X[i] ? "R" : (streamOk_X[i] ? "S" : "-")));
  662. }
  663. }
  664. dprintf("\n");
  665. LocalFree(readOk_X);
  666. LocalFree(streamOk_X);
  667. Depth -= INDENT;
  668. return;
  669. }
  670. VOID
  671. DumpRedBookStreamData(
  672. IN PVOID X,
  673. IN ULONG_PTR Address,
  674. IN ULONG Detail,
  675. IN LONG Depth
  676. )
  677. {
  678. PREDBOOK_STREAM_DATA Stream = X;
  679. xdprintf(Depth, "STREAM DATA at %p\n", Address);
  680. Depth += INDENT;
  681. xdprintf(Depth, " Pin: FileObject %p DeviceObject %p\n",
  682. Stream->PinFileObject,
  683. Stream->PinDeviceObject);
  684. xdprintf(Depth, "Mixer: FileObject %p PinId %x VolumeNodeId %x\n",
  685. Stream->MixerFileObject,
  686. Stream->MixerPinId,
  687. Stream->VolumeNodeId);
  688. xdprintf(Depth, "Connect@ %p Format@ %p (%x and %x bytes)\n",
  689. Address+FIELD_OFFSET(REDBOOK_STREAM_DATA,Connect),
  690. Address+FIELD_OFFSET(REDBOOK_STREAM_DATA,Format),
  691. sizeof(KSPIN_CONNECT),
  692. sizeof(KSDATAFORMAT_WAVEFORMATEX));
  693. Depth -= INDENT;
  694. return;
  695. }
  696. VOID
  697. DumpRedBookThreadData(
  698. IN PVOID X,
  699. IN ULONG_PTR Address,
  700. IN ULONG Detail,
  701. IN LONG Depth
  702. )
  703. {
  704. PREDBOOK_THREAD_DATA Thread = X;
  705. PUCHAR X2 = (PUCHAR)Address;
  706. xdprintf(Depth, "THREAD DATA at %p\n", Address);
  707. Depth += INDENT;
  708. xdprintf(Depth, "Handle %x Pointer %p ",
  709. Thread->SelfHandle,
  710. Thread->SelfPointer
  711. );
  712. if (Thread->IoctlCurrent) {
  713. dprintf("Current Ioctl: %p\n", Thread->IoctlCurrent);
  714. } else {
  715. dprintf("Current Ioctl: None\n");
  716. }
  717. Thread = X; // BUGBUG - remove this, and Thread gets set to zero above?
  718. xdprintf(Depth, "PendingRead %x Pending Stream %x\n",
  719. Thread->PendingRead,
  720. Thread->PendingStream
  721. );
  722. xdprintf(Depth, "IoctlList:");
  723. DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, IoctlList));
  724. dprintf("\n");
  725. xdprintf(Depth, "WmiList:");
  726. DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, WmiList));
  727. dprintf("\n");
  728. xdprintf(Depth, "DigitalList:");
  729. DumpList(X2 + FIELD_OFFSET(REDBOOK_THREAD_DATA, DigitalList));
  730. dprintf("\n");
  731. Depth -= INDENT;
  732. }
  733. VOID
  734. xdprintf(
  735. LONG Depth,
  736. PCCHAR S,
  737. ...
  738. )
  739. {
  740. va_list ap;
  741. LONG i;
  742. CCHAR DebugBuffer[256];
  743. // Tree output as follows:
  744. //
  745. // +- Item
  746. // |
  747. //
  748. //
  749. for (i=0;i<Depth;i++) {
  750. dprintf(" ");
  751. }
  752. va_start(ap, S);
  753. vsprintf(DebugBuffer, S, ap);
  754. dprintf (DebugBuffer);
  755. va_end(ap);
  756. }
  757. VOID
  758. DumpFlags(
  759. LONG Depth,
  760. PUCHAR Name,
  761. ULONG Flags,
  762. PFLAG_NAME FlagTable
  763. )
  764. {
  765. ULONG i;
  766. ULONG mask = 0;
  767. ULONG count = 0;
  768. UCHAR prolog[64];
  769. sprintf(prolog, "%s (0x%08x): ", Name, Flags);
  770. xdprintf(Depth, "%s", prolog);
  771. if(Flags == 0) {
  772. dprintf("NONE\n");
  773. return;
  774. }
  775. memset(prolog, ' ', strlen(prolog));
  776. for(i = 0; FlagTable[i].Name != 0; i++) {
  777. PFLAG_NAME flag = &(FlagTable[i]);
  778. mask |= flag->Flag;
  779. if((Flags & flag->Flag) == flag->Flag) {
  780. //
  781. // print trailing comma
  782. //
  783. if(count != 0) {
  784. dprintf(", ");
  785. //
  786. // Only print two flags per line.
  787. //
  788. if((count % 2) == 0) {
  789. dprintf("\n");
  790. xdprintf(Depth, "%s", prolog);
  791. }
  792. }
  793. dprintf("%s", flag->Name);
  794. count++;
  795. }
  796. }
  797. dprintf("\n");
  798. if((Flags & (~mask)) != 0) {
  799. xdprintf(Depth, "%sUnknown flags %lx\n", prolog, (Flags & (~mask)));
  800. }
  801. return;
  802. }
  803. VOID
  804. GetPointer(
  805. IN ULONG_PTR Address,
  806. OUT ULONG_PTR *Value
  807. )
  808. {
  809. ULONG result;
  810. if(!ReadMemory(Address, (PVOID)*Value, sizeof(ULONG_PTR), &result) ||
  811. result != sizeof(ULONG_PTR)) {
  812. *Value = 0;
  813. }
  814. return;
  815. }
  816. VOID
  817. DumpList(
  818. PVOID AddressOfListHead
  819. )
  820. {
  821. LIST_ENTRY listHead;
  822. LIST_ENTRY current;
  823. LIST_ENTRY slow;
  824. ULONG result;
  825. BOOLEAN advanceSlowList;
  826. if (!ReadMemory((ULONG_PTR)AddressOfListHead,
  827. &listHead,
  828. sizeof(LIST_ENTRY),
  829. &result)) {
  830. dprintf("Unable to read head of list at %p", AddressOfListHead);
  831. return;
  832. }
  833. slow = listHead;
  834. current = listHead;
  835. advanceSlowList = FALSE;
  836. if (current.Flink == AddressOfListHead) {
  837. dprintf("Empty");
  838. return;
  839. }
  840. //
  841. // list is empty when FLink points is AddressOfListHead
  842. // list is looping when Current.BLink == Slow.Blink
  843. //
  844. while (!CheckControlC()) {
  845. if (current.Flink == AddressOfListHead) {
  846. return;
  847. }
  848. //
  849. // print it
  850. //
  851. dprintf(" %p", current.Flink);
  852. //
  853. // advance the list pointers
  854. //
  855. if (!ReadMemory((ULONG_PTR)current.Flink,
  856. &current,
  857. sizeof(LIST_ENTRY),
  858. &result)) {
  859. dprintf(" !! Unable to read memory at %p", AddressOfListHead);
  860. return;
  861. }
  862. if (advanceSlowList) {
  863. // won't fail since current already read this in successfully
  864. ReadMemory((ULONG_PTR)slow.Flink,
  865. &slow,
  866. sizeof(LIST_ENTRY),
  867. &result);
  868. }
  869. advanceSlowList = !advanceSlowList;
  870. //
  871. // check for loops
  872. //
  873. if (current.Blink == slow.Blink) {
  874. dprintf(" !! List %p has a loop!", AddressOfListHead);
  875. return;
  876. }
  877. }
  878. //
  879. // should always exit from above loop
  880. //
  881. }
  882. VOID
  883. GetAddressAndDetailLevelFromArgs(
  884. PCSTR Args,
  885. PULONG_PTR Address,
  886. PULONG Detail
  887. )
  888. {
  889. UCHAR addressBuffer[256];
  890. UCHAR detailBuffer[256];
  891. addressBuffer[0] = '\0';
  892. detailBuffer[0] = '\0';
  893. (VOID)sscanf(Args, "%s %s", addressBuffer, detailBuffer);
  894. addressBuffer[255] = '\0';
  895. detailBuffer[255] = '\0';
  896. *Address = 0;
  897. *Detail = 0;
  898. if (addressBuffer[0] != '\0') {
  899. //
  900. // they provided an address
  901. //
  902. *Address = (ULONG_PTR) GetExpression(addressBuffer);
  903. //
  904. // if that still doesn't parse, print an error
  905. //
  906. if (*Address==0) {
  907. dprintf("An error occured trying to evaluate the address\n");
  908. *Address = 0;
  909. *Detail = 0;
  910. return;
  911. }
  912. //
  913. // if they provided a detail level get it.
  914. //
  915. if (detailBuffer[0] == '\0') {
  916. *Detail = 0;
  917. } else {
  918. *Detail = (ULONG) GetExpression(detailBuffer);
  919. }
  920. }
  921. }
  922. VOID
  923. ParseArguments(
  924. PCSTR Args,
  925. PULONG_PTR Address,
  926. PULONG Detail,
  927. PVOID Block
  928. )
  929. {
  930. ULONG result;
  931. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)Block;
  932. GetAddressAndDetailLevelFromArgs(Args, Address, Detail);
  933. //
  934. // grab this thing as a device object. If it's type field matches what
  935. // we expect then adjust address to point to the actual device extension
  936. //
  937. if(!ReadMemory(*Address, Block, sizeof(DEVICE_OBJECT), &result)) {
  938. xdprintf(0, "Error reading data at address %p\n", *Address);
  939. return;
  940. }
  941. if(deviceObject->Type == IO_TYPE_DEVICE) {
  942. *Address = (ULONG_PTR)deviceObject->DeviceExtension;
  943. }
  944. //
  945. // now get the device extension
  946. //
  947. if(!ReadMemory(*Address, Block, sizeof(REDBOOK_DEVICE_EXTENSION), &result)) {
  948. xdprintf(0, "Error reading device extension at address %p\n", *Address);
  949. return;
  950. }
  951. return;
  952. }
  953. VOID
  954. DumpToc(
  955. IN PVOID X,
  956. IN ULONG_PTR Address,
  957. IN ULONG Detail,
  958. IN LONG Depth
  959. )
  960. {
  961. PCDROM_TOC Toc = X;
  962. PTRACK_DATA trackData;
  963. ULONG numberOfTracks;
  964. ULONG i;
  965. numberOfTracks = Toc->LastTrack - Toc->FirstTrack;
  966. xdprintf(Depth, "TOC at %p\n", Address);
  967. Depth += INDENT;
  968. xdprintf(Depth, "Key for Control Field:\n");
  969. xdprintf(Depth, " P - Preemphasis\n");
  970. xdprintf(Depth, " C - Copy Protect\n");
  971. xdprintf(Depth, " D,A - Data or Audio Track\n");
  972. xdprintf(Depth, " # - Number of Audio Channels\n\n");
  973. xdprintf(Depth, "FirstTrack %x LastTrack %x NumberOfTracks %x Size: %x\n",
  974. Toc->FirstTrack,
  975. Toc->LastTrack,
  976. numberOfTracks,
  977. (Toc->Length[0] << 8) | (Toc->Length[1])
  978. );
  979. xdprintf(Depth, "Index Track Control MSF Address\n");
  980. xdprintf(Depth, "---------------------------------------------\n");
  981. for (i=0,trackData = Toc->TrackData;
  982. (!CheckControlC()) && i<numberOfTracks+2; // lead-in, lead-out track
  983. i++,trackData++) {
  984. ULONG lba;
  985. UCHAR m,s,f;
  986. if (trackData->Reserved || trackData->Reserved1) {
  987. xdprintf(Depth, "TrackData[%x] has reserved fields filled in. "
  988. "Most likely not a TOC\n", i);
  989. return;
  990. }
  991. lba =
  992. (trackData->Address[0] << 24) |
  993. (trackData->Address[1] << 16) |
  994. (trackData->Address[2] << 8) |
  995. (trackData->Address[3] << 0);
  996. LBA_TO_MSF(lba, m, s, f);
  997. m = s = f = 0;
  998. xdprintf(Depth, " %2x %2x %s %s %s %s %02x:%02x:%02x 0x%06x\n",
  999. i,
  1000. trackData->TrackNumber,
  1001. TEST_FLAG(trackData->Control, AUDIO_WITH_PREEMPHASIS) ? "P" : "-",
  1002. TEST_FLAG(trackData->Control, DIGITAL_COPY_PERMITTED) ? "C" : "-",
  1003. TEST_FLAG(trackData->Control, AUDIO_DATA_TRACK) ? "D" : "A",
  1004. TEST_FLAG(trackData->Control, TWO_FOUR_CHANNEL_AUDIO) ? "4" : "2",
  1005. m, s, f, lba
  1006. );
  1007. }
  1008. Depth -= INDENT;
  1009. return;
  1010. }
  1011. VOID
  1012. DumpContext(
  1013. IN PVOID X,
  1014. IN ULONG_PTR Address,
  1015. IN ULONG Detail,
  1016. IN LONG Depth
  1017. )
  1018. {
  1019. PREDBOOK_COMPLETION_CONTEXT Context = X;
  1020. ULONG i;
  1021. xdprintf(Depth, "Context %x for devext %p at %p\n",
  1022. Context->Index, Context->DeviceExtension, Address);
  1023. Depth += INDENT;
  1024. if (Context->ListEntry.Flink != Context->ListEntry.Blink) {
  1025. if (Context->Reason > 4) {
  1026. xdprintf(Depth, "Context is queued for %s\n",
  1027. REDBOOK_CC_STRINGS[ Context->Reason ]);
  1028. } else {
  1029. xdprintf(Depth, "Context is queued for %s\n",
  1030. REDBOOK_CC_STRINGS[ 4 ]);
  1031. }
  1032. }
  1033. xdprintf(Depth, "\\");
  1034. for (i=0;i<2000;i++) {
  1035. UCHAR array[5] = "|/-\\";
  1036. dprintf("\b%c", array[ i%4 ]);
  1037. }
  1038. dprintf("\b \n");
  1039. xdprintf(Depth, "Irp %p Buffer %p Mdl %p\n",
  1040. Context->Irp, Context->Buffer, Context->Mdl);
  1041. xdprintf(Depth,
  1042. "KSSTREAM Header at %p\n",
  1043. Address + FIELD_OFFSET(REDBOOK_COMPLETION_CONTEXT, Header)
  1044. );
  1045. xdprintf(Depth,
  1046. "Size = %x\n",
  1047. Context->Header.Size
  1048. );
  1049. xdprintf(Depth,
  1050. "TypeSpecificFlags = %x\n",
  1051. Context->Header.TypeSpecificFlags
  1052. );
  1053. xdprintf(Depth,
  1054. "Duration = %I64x\n",
  1055. Context->Header.Duration
  1056. );
  1057. xdprintf(Depth,
  1058. "FrameExtent = %x\n",
  1059. Context->Header.FrameExtent
  1060. );
  1061. xdprintf(Depth,
  1062. "DataUsed = %x\n",
  1063. Context->Header.DataUsed
  1064. );
  1065. xdprintf(Depth,
  1066. "Data = %p\n",
  1067. Context->Header.Data
  1068. );
  1069. xdprintf(Depth,
  1070. "OptionsFlags = %x\n",
  1071. Context->Header.OptionsFlags
  1072. );
  1073. xdprintf(Depth,
  1074. "PresentationTime.Time = %I64x\n",
  1075. Context->Header.PresentationTime.Time
  1076. );
  1077. xdprintf(Depth,
  1078. "PresentationTime.Numerator = %x\n",
  1079. Context->Header.PresentationTime.Numerator
  1080. );
  1081. xdprintf(Depth,
  1082. "PresentationTime.Denominator = %x\n",
  1083. Context->Header.PresentationTime.Denominator
  1084. );
  1085. return;
  1086. }