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.

1099 lines
24 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: cdapi.c
  3. *
  4. * This module encapsulates the CD-ROM device into a set of callable apis.
  5. * The api's are implemented using the scsi cdrom IOCTLS.
  6. *
  7. * Created: 02-11-93
  8. * Author: Stephen Estrop [StephenE]
  9. *
  10. * Copyright (c) 1993 Microsoft Corporation
  11. \**************************************************************************/
  12. #ifdef USE_IOCTLS
  13. #pragma warning( once : 4201 4214 )
  14. #define NOOLE
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <ntdddisk.h>
  19. #include <windows.h> /* required for all Windows applications */
  20. #include <windowsx.h>
  21. #include <string.h>
  22. #include "resource.h"
  23. #include "cdplayer.h"
  24. #include "cdapi.h"
  25. #include "scan.h"
  26. #include "trklst.h"
  27. /* -------------------------------------------------------------------------
  28. **
  29. ** High level routines
  30. **
  31. ** -------------------------------------------------------------------------
  32. */
  33. /******************************Public*Routine******************************\
  34. * CheckStatus
  35. *
  36. * Check return code for known bad codes and inform
  37. * user how to correct (if possible) the problem.
  38. *
  39. * History:
  40. * 18-11-93 - StephenE - Created
  41. *
  42. \**************************************************************************/
  43. void
  44. CheckStatus(
  45. LPSTR szCaller,
  46. DWORD status,
  47. int cdrom
  48. )
  49. {
  50. TCHAR s[100];
  51. if (status==ERROR_SUCCESS)
  52. return;
  53. switch( status ) {
  54. case ERROR_GEN_FAILURE:
  55. wsprintf( s, IdStr( STR_ERR_GEN ), g_Devices[cdrom]->drive, szCaller );
  56. break;
  57. case ERROR_NO_MEDIA_IN_DRIVE:
  58. wsprintf( s, IdStr( STR_ERR_NO_MEDIA ), g_Devices[cdrom]->drive );
  59. NoMediaUpdate( cdrom );
  60. break;
  61. case ERROR_UNRECOGNIZED_MEDIA:
  62. wsprintf( s, IdStr( STR_ERR_UNREC_MEDIA ), g_Devices[cdrom]->drive );
  63. if (!(g_Devices[cdrom]->State & CD_DATA_CD_LOADED))
  64. NoMediaUpdate( cdrom );
  65. break;
  66. case ERROR_FILE_NOT_FOUND:
  67. wsprintf( s, IdStr( STR_ERR_NO_DEVICE ), szCaller, g_Devices[cdrom]->drive );
  68. NoMediaUpdate( cdrom );
  69. break;
  70. case ERROR_INVALID_FUNCTION:
  71. wsprintf( s, IdStr( STR_ERR_INV_DEV_REQ ), g_Devices[cdrom]->drive );
  72. break;
  73. case ERROR_NOT_READY:
  74. wsprintf( s, IdStr( STR_ERR_NOT_READY ), g_Devices[cdrom]->drive );
  75. NoMediaUpdate( cdrom );
  76. break;
  77. case ERROR_SECTOR_NOT_FOUND:
  78. wsprintf( s, IdStr( STR_ERR_BAD_SEC ), g_Devices[cdrom]->drive );
  79. break;
  80. case ERROR_IO_DEVICE:
  81. wsprintf( s, IdStr( STR_ERR_IO_ERROR ), g_Devices[cdrom]->drive );
  82. break;
  83. default:
  84. wsprintf( s, IdStr( STR_ERR_DEFAULT ), g_Devices[cdrom]->drive, szCaller, status );
  85. break;
  86. }
  87. #if DBG
  88. /* StatusLine( SL_ERROR, s ); */
  89. SetWindowText( g_hwndStatusbar, s );
  90. #endif
  91. }
  92. /******************************Public*Routine******************************\
  93. * CheckUnitCdrom
  94. *
  95. * Queries the device state, checking to see if a disc has been ejected or
  96. * inserted.
  97. *
  98. * History:
  99. * 18-11-93 - StephenE - Created
  100. *
  101. \**************************************************************************/
  102. void
  103. CheckUnitCdrom(
  104. int cdrom
  105. )
  106. {
  107. DWORD status;
  108. if ( g_Devices[cdrom]->hCd == NULL ) {
  109. HANDLE hTemp;
  110. TCHAR chDevRoot[] = TEXT("\\\\.\\A:");
  111. chDevRoot[4] = g_Devices[cdrom]->drive;
  112. hTemp = CreateFile( chDevRoot, GENERIC_READ,
  113. FILE_SHARE_READ, NULL, OPEN_EXISTING,
  114. FILE_ATTRIBUTE_NORMAL, NULL );
  115. if ( hTemp == INVALID_HANDLE_VALUE ) {
  116. g_Devices[cdrom]->hCd = NULL;
  117. return;
  118. }
  119. else {
  120. g_Devices[cdrom]->hCd = hTemp;
  121. }
  122. }
  123. status = TestUnitReadyCdrom( g_Devices[cdrom]->hCd );
  124. if (g_Devices[cdrom]->State & CD_NO_CD) {
  125. if (status == ERROR_SUCCESS) {
  126. /*
  127. ** A new disc has been inserted, scan it now.
  128. */
  129. RescanDevice( g_hwndApp, cdrom );
  130. }
  131. }
  132. else {
  133. if (status != ERROR_SUCCESS) {
  134. /*
  135. ** Disc has been ejected.
  136. */
  137. NoMediaUpdate( cdrom );
  138. }
  139. }
  140. }
  141. /******************************Public*Routine******************************\
  142. * NoMediaUpdate
  143. *
  144. * Update the user display when it is found that no media is in the device.
  145. *
  146. * History:
  147. * 18-11-93 - StephenE - Created
  148. *
  149. \**************************************************************************/
  150. void
  151. NoMediaUpdate(
  152. int cdrom
  153. )
  154. {
  155. BOOL fChangePlayButtons;
  156. if ( cdrom == g_CurrCdrom ) {
  157. fChangePlayButtons = TRUE;
  158. }
  159. else {
  160. fChangePlayButtons = FALSE;
  161. }
  162. g_Devices[cdrom]->State = (CD_NO_CD | CD_STOPPED);
  163. if (fChangePlayButtons) {
  164. SetPlayButtonsEnableState();
  165. }
  166. TimeAdjustInitialize( cdrom );
  167. }
  168. /******************************Public*Routine******************************\
  169. * EjectTheCdromDisc
  170. *
  171. * Eject the disc from the specified cdrom device.
  172. *
  173. * History:
  174. * 18-11-93 - StephenE - Created
  175. *
  176. \**************************************************************************/
  177. BOOL
  178. EjectTheCdromDisc(
  179. IN INT cdrom
  180. )
  181. {
  182. DWORD status;
  183. /*
  184. ** Stop the drive first
  185. */
  186. status = StopCdrom( g_Devices[cdrom]->hCd );
  187. /*
  188. ** Eject the disc
  189. */
  190. status = EjectCdrom( g_Devices[cdrom]->hCd );
  191. CheckStatus( "EjectCdrom", status, cdrom );
  192. return status == ERROR_SUCCESS;
  193. }
  194. /******************************Public*Routine******************************\
  195. * PlayCurrTrack
  196. *
  197. * Set cdrom device playing from start MSF to end MSF of current
  198. * track.
  199. *
  200. * History:
  201. * 18-11-93 - StephenE - Created
  202. *
  203. \**************************************************************************/
  204. BOOL
  205. PlayCurrTrack(
  206. int cdrom
  207. )
  208. {
  209. DWORD status;
  210. CDROM_PLAY_AUDIO_MSF pam;
  211. int retry,min,sec,endindex;
  212. int i;
  213. PTRACK_PLAY tr;
  214. tr = CURRTRACK( cdrom );
  215. if (tr==NULL) {
  216. return( FALSE );
  217. }
  218. sec = TRACK_S(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurSec;
  219. min = TRACK_M(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurMin;
  220. min += (sec / 60);
  221. sec = (sec % 60);
  222. pam.StartingM = min;
  223. pam.StartingS = sec;
  224. pam.StartingF = TRACK_F(cdrom,tr->TocIndex);
  225. endindex = FindContiguousEnd( cdrom, tr );
  226. pam.EndingM = TRACK_M(cdrom,endindex);
  227. pam.EndingS = TRACK_S(cdrom,endindex);
  228. pam.EndingF = TRACK_F(cdrom,endindex);
  229. /*
  230. ** for some reason, sometimes the lead out track
  231. ** gived bad values, because when we try to
  232. ** play the last track, we get an error. However,
  233. ** if we back up a little bit from what is reported
  234. ** to us as the end of the last track, we can get
  235. ** it to play. Below is a hack to do just that...
  236. */
  237. retry = 0;
  238. do {
  239. status = PlayCdrom( g_Devices[cdrom]->hCd, &pam );
  240. if ( (status != ERROR_SUCCESS)
  241. ) {
  242. /*
  243. ** Didn't play, so try backing off a little bit
  244. ** at the end of the track
  245. */
  246. retry++;
  247. i = (INT)pam.EndingF - 30;
  248. if (i<0) {
  249. pam.EndingF = (UCHAR)(70 + i);
  250. if (pam.EndingS!=0) {
  251. pam.EndingS--;
  252. } else {
  253. pam.EndingS=59;
  254. pam.EndingM--;
  255. }
  256. } else {
  257. pam.EndingF = (UCHAR)i;
  258. }
  259. /*
  260. ** Store the information in our structures so that
  261. ** we don't have to recompute this next time...
  262. */
  263. TRACK_M(cdrom,endindex) = pam.EndingM;
  264. TRACK_S(cdrom,endindex) = pam.EndingS;
  265. TRACK_F(cdrom,endindex) = pam.EndingF;
  266. } else
  267. retry = 15;
  268. } while ((retry<15) && (status!=ERROR_SUCCESS));
  269. CheckStatus( "PlayCurrTrack", status, cdrom );
  270. if (status == ERROR_SUCCESS) {
  271. ValidatePosition( cdrom );
  272. }
  273. return status == ERROR_SUCCESS;
  274. }
  275. /******************************Public*Routine******************************\
  276. * StopTheCdromDrive
  277. *
  278. * Tell the cdrom device to stop playing
  279. *
  280. * History:
  281. * 18-11-93 - StephenE - Created
  282. *
  283. \**************************************************************************/
  284. BOOL
  285. StopTheCdromDrive(
  286. int cdrom
  287. )
  288. {
  289. DWORD status;
  290. status = StopCdrom( g_Devices[cdrom]->hCd );
  291. CheckStatus( "StopCdrom", status, cdrom );
  292. return status == ERROR_SUCCESS;
  293. }
  294. /******************************Public*Routine******************************\
  295. * PauseTheCdromDrive
  296. *
  297. * Tell the cdrom device to pause playing
  298. *
  299. * History:
  300. * 18-11-93 - StephenE - Created
  301. *
  302. \**************************************************************************/
  303. BOOL
  304. PauseTheCdromDrive(
  305. int cdrom
  306. )
  307. {
  308. DWORD status;
  309. status = PauseCdrom( g_Devices[cdrom]->hCd );
  310. CheckStatus( "PauseCdrom", status, cdrom );
  311. return status == ERROR_SUCCESS;
  312. }
  313. /******************************Public*Routine******************************\
  314. * ResumeTheCdromDrive
  315. *
  316. * Tell the cdrom device to resume playing
  317. *
  318. * History:
  319. * 18-11-93 - StephenE - Created
  320. *
  321. \**************************************************************************/
  322. BOOL
  323. ResumeTheCdromDrive(
  324. int cdrom
  325. )
  326. {
  327. DWORD status;
  328. status = ResumeCdrom( g_Devices[cdrom]->hCd );
  329. CheckStatus( "ResumeCdrom", status, cdrom );
  330. if ( status == ERROR_NOT_READY )
  331. NoMediaUpdate( cdrom );
  332. else
  333. ValidatePosition( cdrom );
  334. return status == ERROR_SUCCESS;
  335. }
  336. /******************************Public*Routine******************************\
  337. * SeekToCurrSecond
  338. *
  339. * Seek to the position on the disc represented by the
  340. * current time (position) information in gDevices, and
  341. * continue playing to the end of the current track.
  342. *
  343. * History:
  344. * 18-11-93 - StephenE - Created
  345. *
  346. \**************************************************************************/
  347. BOOL
  348. SeekToCurrSecond(
  349. int cdrom
  350. )
  351. {
  352. DWORD status;
  353. CDROM_PLAY_AUDIO_MSF pam;
  354. int retry,i,endindex;
  355. PTRACK_PLAY tr;
  356. SUB_Q_CHANNEL_DATA subq;
  357. CDROM_SUB_Q_DATA_FORMAT df;
  358. /*
  359. ** Build starting and ending positions for play
  360. */
  361. tr = CDTIME(cdrom).CurrTrack;
  362. if (tr==NULL) {
  363. return( FALSE );
  364. }
  365. /*
  366. ** This routine sometimes wants to play from the current position
  367. ** through the end of the contiguous play. Since the current
  368. ** position is only being stored accurate down to seconds, we get
  369. ** the current position, see if it's reasonably close to our
  370. ** starting position, then start the play from the actual current
  371. ** position.
  372. */
  373. df.Format = IOCTL_CDROM_CURRENT_POSITION;
  374. df.Track = (UCHAR)CDTIME(cdrom).CurrTrack->TocIndex;
  375. GetCdromSubQData( g_Devices[ cdrom ]->hCd, &subq, &df );
  376. pam.StartingM = (UCHAR)(TRACK_M(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurMin);
  377. pam.StartingS = (UCHAR)(TRACK_S(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurSec);
  378. pam.StartingF = 0;
  379. i = pam.StartingM * 60 + pam.StartingS;
  380. i-= (INT) subq.CurrentPosition.AbsoluteAddress[1] * 60;
  381. i-= (INT) subq.CurrentPosition.AbsoluteAddress[2];
  382. if (ABS(i) <= 1) {
  383. pam.StartingM = (INT) subq.CurrentPosition.AbsoluteAddress[1];
  384. pam.StartingS = (INT) subq.CurrentPosition.AbsoluteAddress[2];
  385. pam.StartingF = (INT) subq.CurrentPosition.AbsoluteAddress[3];
  386. }
  387. if (pam.StartingS > 59) {
  388. pam.StartingM++;
  389. pam.StartingS = (UCHAR)(pam.StartingS - 60);
  390. }
  391. if ((CDTIME(cdrom).TrackCurMin==0) && (CDTIME(cdrom).TrackCurSec==0))
  392. pam.StartingF = TRACK_F(cdrom,tr->TocIndex);
  393. if (g_Devices[ cdrom ]->State & CD_PLAYING) {
  394. endindex = FindContiguousEnd( cdrom, tr );
  395. pam.EndingM = TRACK_M(cdrom,endindex);
  396. pam.EndingS = TRACK_S(cdrom,endindex);
  397. pam.EndingF = TRACK_F(cdrom,endindex);
  398. } else {
  399. endindex = 0;
  400. pam.EndingM = pam.StartingM;
  401. pam.EndingS = pam.StartingS;
  402. pam.EndingF = pam.StartingF;
  403. }
  404. retry = 0;
  405. do {
  406. status = PlayCdrom( g_Devices[ cdrom ]->hCd, &pam );
  407. if (status != ERROR_SUCCESS) {
  408. /*
  409. ** Didn't play, so try backing off a little bit
  410. ** at the end of the track
  411. */
  412. retry++;
  413. i = (INT)pam.EndingF - 30;
  414. if (i<0) {
  415. pam.EndingF = (UCHAR)(70 + i);
  416. if (pam.EndingS!=0) {
  417. pam.EndingS--;
  418. } else {
  419. pam.EndingS=59;
  420. pam.EndingM--;
  421. }
  422. } else {
  423. pam.EndingF = (UCHAR)i;
  424. }
  425. /*
  426. ** Store the information in our structures so that
  427. ** we don't have to recompute this next time...
  428. */
  429. TRACK_M(cdrom,endindex) = pam.EndingM;
  430. TRACK_S(cdrom,endindex) = pam.EndingS;
  431. TRACK_F(cdrom,endindex) = pam.EndingF;
  432. } else
  433. retry = 15;
  434. } while ((retry<15) && (status!=ERROR_SUCCESS));
  435. CheckStatus( "SeekToCurrSec", status, cdrom );
  436. if (status == ERROR_SUCCESS) {
  437. ValidatePosition(cdrom);
  438. }
  439. return status == ERROR_SUCCESS;
  440. }
  441. /******************************Public*Routine******************************\
  442. * GetCurrPos
  443. *
  444. * Query cdrom device for its current position and status
  445. * and return information in callers buffer.
  446. *
  447. * History:
  448. * 18-11-93 - StephenE - Created
  449. *
  450. \**************************************************************************/
  451. BOOL
  452. GetCurrPos(
  453. int cdrom,
  454. PCURRPOS CpPtr
  455. )
  456. {
  457. DWORD status;
  458. SUB_Q_CHANNEL_DATA subq;
  459. CDROM_SUB_Q_DATA_FORMAT df;
  460. /*
  461. ** Tell lower layer what we want it to do...in this case,
  462. ** we need to specify which SubQData format we want returned.
  463. ** This is exported from scsicdrom.sys to the user layer
  464. ** so that it could be implemented in one call, instead of
  465. ** four separate calls (there are four SubQData formats)
  466. */
  467. /*
  468. ** Set up for current position SubQData format.
  469. */
  470. df.Format = IOCTL_CDROM_CURRENT_POSITION;
  471. if (CDTIME(cdrom).CurrTrack != NULL) {
  472. df.Track = (UCHAR)CDTIME(cdrom).CurrTrack->TocIndex;
  473. status = GetCdromSubQData( g_Devices[ cdrom ]->hCd, &subq, &df );
  474. }
  475. else {
  476. status = (DWORD)~ERROR_SUCCESS;
  477. }
  478. if (status==ERROR_SUCCESS) {
  479. CpPtr->AudioStatus = subq.CurrentPosition.Header.AudioStatus;
  480. CpPtr->Track = (INT)subq.CurrentPosition.TrackNumber;
  481. CpPtr->Index = (INT)subq.CurrentPosition.IndexNumber;
  482. CpPtr->m = (INT)subq.CurrentPosition.TrackRelativeAddress[1];
  483. CpPtr->s = (INT)subq.CurrentPosition.TrackRelativeAddress[2];
  484. CpPtr->f = (INT)subq.CurrentPosition.TrackRelativeAddress[3];
  485. CpPtr->ab_m = (INT)subq.CurrentPosition.AbsoluteAddress[1];
  486. CpPtr->ab_s = (INT)subq.CurrentPosition.AbsoluteAddress[2];
  487. CpPtr->ab_f = (INT)subq.CurrentPosition.AbsoluteAddress[3];
  488. }
  489. else {
  490. CpPtr->AudioStatus = 0;
  491. CpPtr->Track = 0;
  492. CpPtr->Index = 0;
  493. CpPtr->m = 0;
  494. CpPtr->s = 0;
  495. CpPtr->f = 0;
  496. CpPtr->ab_m = 0;
  497. CpPtr->ab_s = 0;
  498. CpPtr->ab_f = 0;
  499. }
  500. CheckStatus( "GetCurrPos", status, cdrom );
  501. return status==ERROR_SUCCESS;
  502. }
  503. /******************************Public*Routine******************************\
  504. * SeekToTrackAndHold
  505. *
  506. * Seek to specified track and enter hold state.
  507. *
  508. * History:
  509. * 18-11-93 - StephenE - Created
  510. *
  511. \**************************************************************************/
  512. BOOL
  513. SeekToTrackAndHold(
  514. int cdrom,
  515. int tindex
  516. )
  517. {
  518. DWORD status;
  519. CDROM_SEEK_AUDIO_MSF sam;
  520. sam.M = TRACK_M(cdrom,tindex);
  521. sam.S = TRACK_S(cdrom,tindex);
  522. sam.F = TRACK_F(cdrom,tindex);
  523. status = SeekCdrom( g_Devices[ cdrom ]->hCd, &sam );
  524. CheckStatus( "SeekToTrackAndHold", status, cdrom );
  525. if (status == ERROR_SUCCESS) {
  526. ValidatePosition( cdrom );
  527. }
  528. return status == ERROR_SUCCESS;
  529. }
  530. /* -------------------------------------------------------------------------
  531. **
  532. ** Low level routines
  533. **
  534. ** -------------------------------------------------------------------------
  535. */
  536. /******************************Public*Routine******************************\
  537. * GetCdromTOC
  538. *
  539. * This routine will get the table of contents from
  540. * a CDRom device.
  541. *
  542. *
  543. * History:
  544. * 18-11-93 - StephenE - Created
  545. *
  546. \**************************************************************************/
  547. DWORD
  548. GetCdromTOC(
  549. HANDLE DeviceHandle,
  550. PCDROM_TOC TocPtr
  551. )
  552. {
  553. DWORD bytesRead;
  554. if (DeviceIoControl( DeviceHandle,
  555. IOCTL_CDROM_READ_TOC,
  556. NULL,
  557. 0,
  558. (LPVOID)TocPtr,
  559. sizeof(CDROM_TOC),
  560. &bytesRead,
  561. NULL )) {
  562. return ERROR_SUCCESS;
  563. }
  564. else {
  565. return GetLastError();
  566. }
  567. }
  568. /******************************Public*Routine******************************\
  569. * StopCdrom
  570. *
  571. * This routine will stop a CDRom device that is playing.
  572. *
  573. *
  574. * History:
  575. * 18-11-93 - StephenE - Created
  576. *
  577. \**************************************************************************/
  578. DWORD
  579. StopCdrom(
  580. HANDLE DeviceHandle
  581. )
  582. {
  583. DWORD bytesRead;
  584. if (DeviceIoControl( DeviceHandle,
  585. IOCTL_CDROM_STOP_AUDIO,
  586. NULL,
  587. 0,
  588. NULL,
  589. 0,
  590. &bytesRead,
  591. NULL )) {
  592. return ERROR_SUCCESS;
  593. }
  594. else {
  595. return GetLastError();
  596. }
  597. }
  598. /******************************Public*Routine******************************\
  599. * PauseCdrom
  600. *
  601. * This routine will pause a CDRom device.
  602. *
  603. * History:
  604. * 18-11-93 - StephenE - Created
  605. *
  606. \**************************************************************************/
  607. DWORD
  608. PauseCdrom(
  609. HANDLE DeviceHandle
  610. )
  611. {
  612. DWORD bytesRead;
  613. if (DeviceIoControl( DeviceHandle,
  614. IOCTL_CDROM_PAUSE_AUDIO,
  615. NULL,
  616. 0,
  617. NULL,
  618. 0,
  619. &bytesRead,
  620. NULL )) {
  621. return ERROR_SUCCESS;
  622. }
  623. else {
  624. return GetLastError();
  625. }
  626. }
  627. /******************************Public*Routine******************************\
  628. * ResumeCdrom
  629. *
  630. * This routine will resume a paused CDRom device.
  631. *
  632. * History:
  633. * 18-11-93 - StephenE - Created
  634. *
  635. \**************************************************************************/
  636. DWORD
  637. ResumeCdrom(
  638. HANDLE DeviceHandle
  639. )
  640. {
  641. DWORD bytesRead;
  642. if (DeviceIoControl( DeviceHandle,
  643. IOCTL_CDROM_RESUME_AUDIO,
  644. NULL,
  645. 0,
  646. NULL,
  647. 0,
  648. &bytesRead,
  649. NULL )) {
  650. return ERROR_SUCCESS;
  651. }
  652. else {
  653. return GetLastError();
  654. }
  655. }
  656. /******************************Public*Routine******************************\
  657. * PlayCdrom
  658. *
  659. * This routine plays a CDRom device starting and ending at the MSF
  660. * positions specified in the structure passed in.
  661. *
  662. * History:
  663. * 18-11-93 - StephenE - Created
  664. *
  665. \**************************************************************************/
  666. DWORD
  667. PlayCdrom(
  668. HANDLE DeviceHandle,
  669. PCDROM_PLAY_AUDIO_MSF PlayAudioPtr
  670. )
  671. {
  672. DWORD bytesRead;
  673. if (DeviceIoControl( DeviceHandle,
  674. IOCTL_CDROM_PLAY_AUDIO_MSF,
  675. (LPVOID)PlayAudioPtr,
  676. sizeof(CDROM_PLAY_AUDIO_MSF),
  677. NULL,
  678. 0,
  679. &bytesRead,
  680. NULL )) {
  681. return ERROR_SUCCESS;
  682. }
  683. else {
  684. return GetLastError();
  685. }
  686. }
  687. /******************************Public*Routine******************************\
  688. * GetCdromSubQData
  689. *
  690. * DeviceHandle - Handle to CDRom device to retrieve information from.
  691. * SubQPtr - A pointer to a SUB_Q_CHANNEL_DATA structure to be filled in by
  692. * this routine.
  693. *
  694. *
  695. * History:
  696. * 18-11-93 - StephenE - Created
  697. *
  698. \**************************************************************************/
  699. DWORD
  700. GetCdromSubQData(
  701. HANDLE DeviceHandle,
  702. PSUB_Q_CHANNEL_DATA SubQDataPtr,
  703. PCDROM_SUB_Q_DATA_FORMAT SubQFormatPtr
  704. )
  705. {
  706. DWORD bytesRead;
  707. if (DeviceIoControl( DeviceHandle,
  708. IOCTL_CDROM_READ_Q_CHANNEL,
  709. (LPVOID)SubQFormatPtr,
  710. sizeof(CDROM_SUB_Q_DATA_FORMAT),
  711. (LPVOID)SubQDataPtr,
  712. sizeof(SUB_Q_CHANNEL_DATA),
  713. &bytesRead,
  714. NULL )) {
  715. return ERROR_SUCCESS;
  716. }
  717. else {
  718. return GetLastError();
  719. }
  720. }
  721. /******************************Public*Routine******************************\
  722. * SeekCdrom
  723. *
  724. * This routine seek to an MSF address on the audio CD and enters
  725. * a hold (paused) state.
  726. *
  727. *
  728. * History:
  729. * 18-11-93 - StephenE - Created
  730. *
  731. \**************************************************************************/
  732. DWORD
  733. SeekCdrom(
  734. HANDLE DeviceHandle,
  735. PCDROM_SEEK_AUDIO_MSF SeekAudioPtr
  736. )
  737. {
  738. DWORD bytesRead;
  739. if (DeviceIoControl( DeviceHandle,
  740. IOCTL_CDROM_SEEK_AUDIO_MSF,
  741. (LPVOID)SeekAudioPtr,
  742. sizeof(CDROM_SEEK_AUDIO_MSF),
  743. NULL,
  744. 0,
  745. &bytesRead,
  746. NULL )) {
  747. return ERROR_SUCCESS;
  748. }
  749. else {
  750. return GetLastError();
  751. }
  752. }
  753. /******************************Public*Routine******************************\
  754. * EjectCdrom
  755. *
  756. * This routine will eject a disc from a CDRom device.
  757. *
  758. * History:
  759. * 18-11-93 - StephenE - Created
  760. *
  761. \**************************************************************************/
  762. DWORD
  763. EjectCdrom(
  764. HANDLE DeviceHandle
  765. )
  766. {
  767. DWORD bytesRead;
  768. if (DeviceIoControl( DeviceHandle,
  769. IOCTL_CDROM_EJECT_MEDIA,
  770. NULL,
  771. 0,
  772. NULL,
  773. 0,
  774. &bytesRead,
  775. NULL )) {
  776. return ERROR_SUCCESS;
  777. }
  778. else {
  779. return GetLastError();
  780. }
  781. }
  782. /******************************Public*Routine******************************\
  783. * TestUnitReadyCdrom
  784. *
  785. * This routine will retrieve the status of the CDRom device.
  786. *
  787. * History:
  788. * 18-11-93 - StephenE - Created
  789. *
  790. \**************************************************************************/
  791. DWORD
  792. TestUnitReadyCdrom(
  793. HANDLE DeviceHandle
  794. )
  795. {
  796. DWORD bytesRead;
  797. if (DeviceIoControl( DeviceHandle,
  798. IOCTL_DISK_CHECK_VERIFY,
  799. NULL,
  800. 0,
  801. NULL,
  802. 0,
  803. &bytesRead,
  804. NULL )) {
  805. return ERROR_SUCCESS;
  806. }
  807. else {
  808. return GetLastError();
  809. }
  810. }
  811. #if 0
  812. /******************************Public*Routine******************************\
  813. * GetCdromVolume
  814. *
  815. * This routine will get the table of contents from
  816. * a CDRom device.
  817. *
  818. *
  819. * History:
  820. * 18-11-93 - StephenE - Created
  821. *
  822. \**************************************************************************/
  823. DWORD
  824. GetCdromVolume(
  825. HANDLE DeviceHandle
  826. )
  827. {
  828. DWORD bytesRead;
  829. VOLUME_CONTROL vc;
  830. TCHAR buff[80];
  831. ZeroMemory( &vc, sizeof(vc) );
  832. if (DeviceIoControl( DeviceHandle,
  833. IOCTL_CDROM_GET_VOLUME,
  834. NULL,
  835. 0,
  836. (LPVOID)&vc,
  837. sizeof(vc),
  838. &bytesRead,
  839. NULL )) {
  840. wsprintf( buff, "%d %d %d %d\n", vc.PortVolume[0], vc.PortVolume[1],
  841. vc.PortVolume[2], vc.PortVolume[3] );
  842. OutputDebugString( buff );
  843. return ERROR_SUCCESS;
  844. }
  845. else {
  846. return GetLastError();
  847. }
  848. }
  849. #endif
  850. #endif