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.

747 lines
19 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cddump.c
  5. Abstract:
  6. parses commands and acts
  7. Environment:
  8. User mode only
  9. Revision History:
  10. 05-26-98 : Created
  11. --*/
  12. #include "common.h"
  13. #define VERSION_MAJOR 1
  14. #define VERSION_MINOR 0
  15. #define VERSION_STRING "1.00"
  16. ULONG32
  17. TestCommand(
  18. HANDLE device,
  19. int argc,
  20. char *argv[]
  21. );
  22. ULONG32
  23. ListCommand(
  24. HANDLE device,
  25. int argc,
  26. char *argv[]
  27. );
  28. ULONG32
  29. DumpTrackCommand(
  30. HANDLE device,
  31. int argc,
  32. char *argv[]
  33. );
  34. ULONG32
  35. VerifyHeaderCommand(
  36. HANDLE device,
  37. int argc,
  38. char *argv[]
  39. );
  40. ULONG32
  41. ReadTOCCommand(
  42. HANDLE device,
  43. int argc,
  44. char *argv[]
  45. );
  46. ULONG32
  47. DumpSectorCommand(
  48. HANDLE device,
  49. int argc,
  50. char *argv[]
  51. );
  52. //
  53. // Each structure instance can have a function pointer, name, and description
  54. //
  55. typedef struct {
  56. char *Name;
  57. char *Description;
  58. ULONG32 (*Function)(HANDLE device, int argc, char *argv[]);
  59. } COMMAND;
  60. //
  61. // List of commands
  62. // all command names are case sensitive
  63. // arguments are passed into command routines
  64. // list must be terminated with NULL command
  65. // command will not be listed in help if description == NULL
  66. //
  67. COMMAND CommandArray[] = {
  68. {"test", NULL, TestCommand},
  69. {"help", "help for all commands", ListCommand},
  70. {"dump", "[track] dump an audio track", DumpTrackCommand},
  71. {"toc", "prints the table of contents", ReadTOCCommand},
  72. {"header", "[file] verifies the info in the wav header", VerifyHeaderCommand},
  73. {"sector", "dumps a given redbook sector", DumpSectorCommand},
  74. {NULL, NULL, NULL}
  75. };
  76. int __cdecl main(int argc, char *argv[])
  77. /*++
  78. Routine Description:
  79. Parses input, showing help or calling function requested appropriately
  80. Return Value:
  81. 0 - success
  82. -1 - insufficient arguments
  83. -2 - error opening device (DNE?)
  84. --*/
  85. {
  86. int i = 0;
  87. int buflen;
  88. char *buffer;
  89. HANDLE h;
  90. HRESULT hr;
  91. if ( argc < 3 ) {
  92. ListCommand( NULL, argc, argv );
  93. return -1;
  94. }
  95. buflen = ( strlen(argv[1]) + 5 ) * sizeof(char);
  96. buffer = (char *)malloc( buflen );
  97. if (buffer == NULL) {
  98. fprintf(stderr, "Insufficient memory\n");
  99. return -1;
  100. }
  101. hr = StringCbPrintf(buffer, buflen, "\\\\.\\%s", argv[1]);
  102. if (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) {
  103. fprintf(stderr, "Unable to format device string (too long?)\n");
  104. free(buffer);
  105. return -9;
  106. } else if (!SUCCEEDED(hr)) {
  107. fprintf(stderr, "Unable to format device string\n");
  108. free(buffer);
  109. return -9;
  110. }
  111. DebugPrint((2, "Main => Sending command %s to drive %s\n", argv[2], buffer));
  112. h = CreateFile( buffer,
  113. GENERIC_READ,
  114. FILE_SHARE_READ,
  115. NULL,
  116. OPEN_EXISTING,
  117. FILE_ATTRIBUTE_NORMAL,
  118. NULL);
  119. if ( h == INVALID_HANDLE_VALUE ) {
  120. fprintf(stderr, "Error %d opening device %s\n", GetLastError(), buffer);
  121. return -2;
  122. }
  123. //
  124. // Iterate through the command array and find the correct function to
  125. // call.
  126. //
  127. while ( CommandArray[i].Name != NULL ) {
  128. if(strcmp(argv[2], CommandArray[i].Name) == 0) {
  129. (CommandArray[i].Function)(h, (argc - 2), &(argv[2]));
  130. break;
  131. }
  132. i++;
  133. }
  134. if ( CommandArray[i].Name == NULL ) {
  135. fprintf(stderr, "Unknown command %s\n", argv[2]);
  136. }
  137. CloseHandle(h);
  138. return 0;
  139. }
  140. ULONG32
  141. VerifyHeaderCommand(
  142. HANDLE device,
  143. int argc,
  144. char *argv[]
  145. )
  146. /*++
  147. Routine Description:
  148. opens the next argument and reads the wav header, printing to stdout
  149. Arguments:
  150. device - unused
  151. argc - the number of additional arguments.
  152. argv - the additional arguments
  153. Return Value:
  154. STATUS_SUCCESS if successful
  155. The value of GetLastError() from the point of failure
  156. --*/
  157. {
  158. HANDLE wavHandle;
  159. if (argv[1] == NULL) {
  160. fprintf(stderr, "Need filename to attempt to parse\n");
  161. return -1;
  162. }
  163. TRY {
  164. DebugPrint((2, "VerifyHeader => Opening %s\n", argv[1]));
  165. wavHandle = CreateFile(argv[1],
  166. GENERIC_READ,
  167. FILE_SHARE_READ,
  168. NULL,
  169. OPEN_EXISTING,
  170. FILE_ATTRIBUTE_NORMAL,
  171. NULL);
  172. if (wavHandle == INVALID_HANDLE_VALUE) {
  173. printf("Error openingfile %x\n", GetLastError());
  174. LEAVE;
  175. }
  176. ReadWavHeader(wavHandle);
  177. CloseHandle(wavHandle);
  178. } FINALLY {
  179. }
  180. return 0;
  181. }
  182. ULONG32 TestCommand(HANDLE device, int argc, char *argv[])
  183. /*++
  184. Routine Description:
  185. Tests the command "parsing"
  186. Arguments:
  187. device - a file handle to send the ioctl to
  188. argc - the number of additional arguments.
  189. argv - the additional arguments
  190. Return Value:
  191. STATUS_SUCCESS if successful
  192. The value of GetLastError() from the point of failure
  193. --*/
  194. {
  195. int i;
  196. printf("Test - %d additional arguments\n", argc);
  197. for(i = 0; i < argc; i++) {
  198. printf("arg %d: %s\n", i, argv[i]);
  199. }
  200. return STATUS_SUCCESS;
  201. }
  202. ULONG32 ListCommand(HANDLE device, int argc, char *argv[])
  203. /*++
  204. Routine Description:
  205. Prints out the command list
  206. Arguments:
  207. device - unused
  208. argc - unused
  209. argv - unused
  210. Return Value:
  211. STATUS_SUCCESS
  212. --*/
  213. {
  214. int i;
  215. printf("\nCdDump Version " VERSION_STRING "\n");
  216. printf("\tUsage: cddump <drive> <command> [parameters]\n");
  217. printf("\tpossible commands: \n");
  218. for (i = 0; CommandArray[i].Name != NULL; i++) {
  219. if(CommandArray[i].Description != NULL) {
  220. printf( "\t\t%s - %s\n",
  221. CommandArray[i].Name,
  222. CommandArray[i].Description
  223. );
  224. }
  225. }
  226. printf( "\n" );
  227. return STATUS_SUCCESS;
  228. }
  229. ULONG32 ReadTOCCommand(HANDLE device, int argc, char *argv[])
  230. /*++
  231. Routine Description:
  232. Reads and prints out the cdrom's table of contents
  233. Arguments:
  234. device - a file handle to send the ioctl to
  235. argc - the number of additional arguments. should be zero
  236. argv - the additional arguments
  237. Return Value:
  238. STATUS_SUCCESS if successful
  239. The value of GetLastError() from the point of failure
  240. --*/
  241. {
  242. PCDROM_TOC toc;
  243. PTRACK_DATA track;
  244. ULONG numberOfTracks;
  245. ULONG i;
  246. DebugPrint((2, "ReadToc => Reading Table of Contents\n"));
  247. toc = CddumpGetToc( device );
  248. if (toc == NULL) {
  249. return -1;
  250. }
  251. printf("First Track Number: %d\n", toc->FirstTrack);
  252. printf("Last Track Number: %d\n", toc->LastTrack);
  253. printf("CDDB ID: %08x\n", CDDB_ID(toc));
  254. numberOfTracks = (toc->LastTrack - toc->FirstTrack) + 1;
  255. // parse and print the information
  256. track = (PTRACK_DATA) &(toc->TrackData[0]);
  257. printf("Number ADR Control Start End Bytes\n");
  258. printf("------ --- ------- ---------- ---------- ----------\n");
  259. for(i = 0; i < numberOfTracks; i++) {
  260. ULONG trackStart;
  261. ULONG trackEnd;
  262. ULONG trackBytes;
  263. trackStart = MSF_TO_LBA(track->Address[1],
  264. track->Address[2],
  265. track->Address[3]);
  266. trackEnd = MSF_TO_LBA((track+1)->Address[1],
  267. (track+1)->Address[2],
  268. (track+1)->Address[3]);
  269. trackEnd--;
  270. trackBytes = (trackEnd - trackStart) * RAW_SECTOR_SIZE;
  271. printf(" %2d %2d %2d %10d %10d %8dk \n",
  272. track->TrackNumber,
  273. track->Adr,
  274. track->Control,
  275. trackStart,
  276. trackEnd,
  277. trackBytes / 1000
  278. );
  279. track++;
  280. }
  281. return STATUS_SUCCESS;
  282. }
  283. ULONG32 DumpTrackCommand(HANDLE device, int argc, char *argv[])
  284. /*++
  285. Routine Description:
  286. Reads a section of disc in raw read mode
  287. Arguments:
  288. device - a file handle to send the ioctl to
  289. argc - the number of additional arguments.
  290. argv[1] - the starting LBA. Starts at zero if this is not here
  291. argv[2] - the ending LBA. if not specified, equal to start
  292. Return Value:
  293. STATUS_SUCCESS if successful
  294. The value of GetLastError() from the point of failure
  295. --*/
  296. {
  297. PCDROM_TOC toc;
  298. HANDLE outputFile = (HANDLE)-1;
  299. HRESULT hr;
  300. ULONG track;
  301. ULONG endingSector;
  302. ULONG numberOfSectors; // actually useful data
  303. ULONG numberOfReads;
  304. ULONG status;
  305. ULONG startingSector;
  306. LONG i;
  307. ULONG cddbId = 0;
  308. UCHAR fileName[1024]; // randomly chosen size.
  309. PSAMPLE sample;
  310. toc = NULL;
  311. sample = NULL;
  312. TRY {
  313. track = atoi(argv[1]);
  314. if (track==0) {
  315. printf( "Cannot read track 0.\n" );
  316. status = -1;
  317. LEAVE;
  318. }
  319. toc = CddumpGetToc( device );
  320. if (toc==NULL) {
  321. status = -1;
  322. LEAVE;
  323. }
  324. cddbId = CDDB_ID(toc);
  325. hr = StringCbPrintf(fileName,
  326. sizeof(fileName),
  327. "%08x - Track %02d.wav",
  328. cddbId, track);
  329. if (HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) {
  330. fprintf(stderr, "Unable to format device string (too long?)\n");
  331. status = -1;
  332. LEAVE;
  333. } else if (!SUCCEEDED(hr)) {
  334. fprintf(stderr, "Unable to format device string\n");
  335. status = -1;
  336. LEAVE;
  337. }
  338. DebugPrint((2, "DumpTrack => output filename: %s\n", fileName));
  339. //
  340. // account for zero-index
  341. //
  342. startingSector = MSF_TO_LBA(toc->TrackData[track-1].Address[1],
  343. toc->TrackData[track-1].Address[2],
  344. toc->TrackData[track-1].Address[3]
  345. );
  346. endingSector = MSF_TO_LBA(toc->TrackData[track].Address[1],
  347. toc->TrackData[track].Address[2],
  348. toc->TrackData[track].Address[3]
  349. );
  350. endingSector--; // no overlap
  351. numberOfSectors = endingSector - startingSector;
  352. DebugPrint((3, "DumpTrack => old sectors: start %8d end %8d count %d\n",
  353. startingSector, endingSector, numberOfSectors));
  354. sample = (PSAMPLE)malloc( RAW_SECTOR_SIZE );
  355. if ( sample == NULL ) {
  356. printf("Insufficient resources (sample)\n");
  357. status = -1;
  358. LEAVE;
  359. }
  360. //
  361. // first find a fully zero'd sample -- that will be
  362. // the _real_ start address of the track after adjusting
  363. // for redbook inaccuracies.
  364. //
  365. for (i=REDBOOK_INACCURACY; i > -(REDBOOK_INACCURACY); i--) {
  366. RAW_READ_INFO info;
  367. ULONG bytesReturned;
  368. ULONG j;
  369. BOOLEAN foundZeroSector = FALSE;
  370. if ((LONG)startingSector + i > 0 ) { // only read positive
  371. info.DiskOffset.QuadPart = (ULONGLONG)((startingSector + i)*(ULONGLONG)2048);
  372. info.SectorCount = 1;
  373. info.TrackMode = CDDA;
  374. if(DeviceIoControl(device,
  375. IOCTL_CDROM_RAW_READ,
  376. &info, // pointer to inputbuffer
  377. sizeof(RAW_READ_INFO), // sizeof inputbuffer
  378. sample, // pointer to outputbuffer
  379. RAW_SECTOR_SIZE, // sizeof outputbuffer
  380. &bytesReturned, // pointer to number of bytes returned
  381. FALSE)) {
  382. //
  383. // read succeeded, see if all zero'd
  384. //
  385. assert(bytesReturned == RAW_SECTOR_SIZE);
  386. foundZeroSector = TRUE;
  387. for (j=0;j<SAMPLES_PER_SECTOR;j++) {
  388. if (sample[j].AsUlong32 != 0) foundZeroSector = FALSE;
  389. }
  390. }
  391. if (foundZeroSector) {
  392. DebugPrint((1, "DumpTrack => New starting sector is "
  393. "offset by %d\n", i));
  394. startingSector += i; // change to real starting sector
  395. break; // stop looping.
  396. }
  397. } // end of positive check
  398. } // end of loop
  399. //
  400. // then find a fully zero'd sample at the end -- that will
  401. // be the _real_ end address of the track after adjusting
  402. // for redbook inaccuracies.
  403. //
  404. for (i=-(REDBOOK_INACCURACY); i < REDBOOK_INACCURACY; i++) {
  405. RAW_READ_INFO info;
  406. ULONG bytesReturned;
  407. ULONG j;
  408. BOOLEAN foundZeroSector = FALSE;
  409. if ((LONG)endingSector + i > 0 ) { // only read positive
  410. info.DiskOffset.QuadPart = (ULONGLONG)((endingSector + i)*(ULONGLONG)2048);
  411. info.SectorCount = 1;
  412. info.TrackMode = CDDA;
  413. if(DeviceIoControl(device,
  414. IOCTL_CDROM_RAW_READ,
  415. &info, // pointer to inputbuffer
  416. sizeof(RAW_READ_INFO), // sizeof inputbuffer
  417. sample, // pointer to outputbuffer
  418. RAW_SECTOR_SIZE, // sizeof outputbuffer
  419. &bytesReturned, // pointer to number of bytes returned
  420. FALSE)) {
  421. //
  422. // read succeeded, see if all zero'd
  423. //
  424. assert(bytesReturned == RAW_SECTOR_SIZE);
  425. foundZeroSector = TRUE;
  426. for (j=0;j<SAMPLES_PER_SECTOR;j++) {
  427. if (sample[j].AsUlong32 != 0) foundZeroSector = FALSE;
  428. }
  429. }
  430. if (foundZeroSector) {
  431. DebugPrint((2, "DumpTrack => New starting sector is "
  432. "offset by %d\n", i));
  433. endingSector += i; // change to real starting sector
  434. break; // stop looping.
  435. }
  436. } // end of positive check
  437. } // end of loop
  438. numberOfSectors = endingSector - startingSector;
  439. DebugPrint((2, "DumpTrack => new sectors: start %8d end %8d count %d\n",
  440. startingSector, endingSector, numberOfSectors));
  441. //
  442. // a bit of debugging info...
  443. //
  444. DebugPrint((2, "DumpTrack => Reading %d sectors starting at sector %d\n",
  445. numberOfSectors, startingSector));
  446. //
  447. // create the file
  448. //
  449. outputFile = CreateFile(fileName,
  450. GENERIC_WRITE,
  451. 0,
  452. NULL,
  453. CREATE_ALWAYS,
  454. FILE_ATTRIBUTE_NORMAL,
  455. (HANDLE)NULL);
  456. if (outputFile == INVALID_HANDLE_VALUE) {
  457. printf( "Cannot open output file.\n" );
  458. status = -1;
  459. LEAVE;
  460. }
  461. //
  462. // dump the wav header info
  463. //
  464. DumpWavHeader(outputFile,
  465. numberOfSectors * SAMPLES_PER_SECTOR,
  466. 44100, // 44.1KHz sound
  467. 2, // stereo sound
  468. 16 // 16-bit sound
  469. );
  470. CddumpDumpLba(device,
  471. outputFile,
  472. startingSector,
  473. endingSector
  474. );
  475. DebugPrint((2, "DumpTrack => Done!\n"));
  476. CloseHandle(outputFile);
  477. } FINALLY {
  478. free(toc);
  479. free(sample);
  480. }
  481. return STATUS_SUCCESS;
  482. }
  483. ULONG32 DumpSectorCommand(HANDLE device, int argc, char *argv[])
  484. /*++
  485. Routine Description:
  486. Reads a section of disc in raw read mode
  487. Arguments:
  488. device - a file handle to send the ioctl to
  489. argc - the number of additional arguments.
  490. argv[1] - the starting LBA. Starts at zero if this is not here
  491. argv[2] - the ending LBA. if not specified, equal to start
  492. Return Value:
  493. STATUS_SUCCESS if successful
  494. The value of GetLastError() from the point of failure
  495. --*/
  496. {
  497. HRESULT hr;
  498. ULONG sector;
  499. ULONG status;
  500. PSAMPLE sample;
  501. sample = NULL;
  502. TRY {
  503. sector = atoi(argv[1]);
  504. printf( "Reading sector %x.\n", sector );
  505. sample = (PSAMPLE)malloc( RAW_SECTOR_SIZE );
  506. if ( sample == NULL ) {
  507. printf("Insufficient resources (sample)\n");
  508. status = -1;
  509. LEAVE;
  510. }
  511. {
  512. RAW_READ_INFO info;
  513. ULONG bytesReturned;
  514. BOOLEAN foundZeroSector = FALSE;
  515. info.DiskOffset.QuadPart = (ULONGLONG)((sector)*(ULONGLONG)2048);
  516. info.SectorCount = 1;
  517. info.TrackMode = CDDA;
  518. if(DeviceIoControl(device,
  519. IOCTL_CDROM_RAW_READ,
  520. &info, // pointer to inputbuffer
  521. sizeof(RAW_READ_INFO), // sizeof inputbuffer
  522. sample, // pointer to outputbuffer
  523. RAW_SECTOR_SIZE, // sizeof outputbuffer
  524. &bytesReturned, // pointer to number of bytes returned
  525. FALSE)) {
  526. //
  527. // read succeeded, see if all zero'd
  528. //
  529. assert(bytesReturned == RAW_SECTOR_SIZE);
  530. }
  531. else
  532. {
  533. printf("Error: %x\n", GetLastError());
  534. }
  535. }
  536. } FINALLY {
  537. free(sample);
  538. }
  539. return STATUS_SUCCESS;
  540. }