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.

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