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.

500 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: redbook.h
  8. //
  9. //--------------------------------------------------------------------------
  10. //////////////////////////////////////////////////////////
  11. #ifndef __REDBOOK_H__
  12. #define __REDBOOK_H__
  13. //
  14. // these two includes required for stuctures
  15. // used in device extension for kernel streaming
  16. //
  17. #include <ntddk.h>
  18. #include <ntddscsi.h>
  19. #include <ntddcdrm.h>
  20. #include <ntdddisk.h> // IOCTL_DISK_CHECK_VERIFY
  21. #include <ntddredb.h> // wmi structure and ids
  22. #include <stdio.h> // vsprintf()
  23. #include <wmistr.h> // WMIREG_FLAG_INSTANCE_PDO
  24. #include <wmilib.h> // WMILIB_CONTEXT
  25. #include <windef.h> // for ks.h
  26. #include <ks.h> // for mmsystem.h
  27. #include <mmsystem.h> // for ksmedia.h
  28. #include <ksmedia.h> // required.
  29. #include "errlog.h"
  30. #include "trace.h" // ETW enabling
  31. #ifndef POOL_TAGGING
  32. #ifdef ExAllocatePoolWithTag
  33. #undef ExAllocatePoolWithTag
  34. #endif
  35. #define ExAllocatePoolWithTag(a,b,c) ExAllocatePool(a,b)
  36. #ifdef ExAllocatePoolWithTagPriority
  37. #undef ExAllocatePoolWithTagPriority
  38. #endif
  39. #define ExAllocatePoolWithTagPriority(a,b,c,d) ExAllocatePool(a,b)
  40. #endif // endif POOL_TAGGING
  41. #define MOFRESOURCENAME L"Redbook"
  42. // static alloc's
  43. #define TAG_GET_DESC 'edBR' // storage descriptor (returned to caller)
  44. #define TAG_GET_DESC1 '1dBR' // getting storage descriptor
  45. #define TAG_GET_DESC2 '2dBR' // getting storage descriptor
  46. #define TAG_MODE_PAGE 'apBR' // mode pages (returned to caller)
  47. #define TAG_MODE_PAGE1 '1pBR' // getting mode pages
  48. #define TAG_MODE_PAGE2 '2pBR' // getting mode pages
  49. #define TAG_EVENTS 'veBR' // extension->Thread.Events[]
  50. #define TAG_REGPATH 'grBR' // driverExtensionObject->RegistryPath
  51. #define TAG_REMLOCK 'lrBR' // Remove lock
  52. #define TAG_T_IOCTL 'itBR' // THREAD_IOCTL struct
  53. #define TAG_T_WMI 'wtBR' // THREAD_WMI struct
  54. #define TAG_T_DIGITAL 'dtBR' // THREAD_DIGITAL struct
  55. // allocs when playing
  56. #define TAG_BUFFER 'uBBR' // Buffer->SkipBuffer
  57. #define TAG_CC 'cCBR' // Buffer->StreamContext
  58. #define TAG_READX 'xRBR' // Buffer->ReadOk_X
  59. #define TAG_STREAMX 'xSBR' // Buffer->StreamOk_X
  60. #define TAG_TOC 'oTBR' // deviceExtension->Cached.Toc
  61. #define TAG_CV_BUFFER 'vCBR' // deviceExtension->Thread.CheckVerifyIrp->AssociatedIrp.SystemBuffer
  62. #define CD_STOPPED 0x00000001
  63. #define CD_PAUSED 0x00000002
  64. #define CD_PLAYING 0x00000004
  65. #define CD_STOPPING 0x00000010 // temp states
  66. #define CD_PAUSING 0x00000020 // temp states
  67. // NOTE: CD_MASK_STATE must have exactly one bit set.
  68. // NOTE: CD_MASK_TEMP may have zero or one bit set.
  69. #define CD_MASK_TEMP 0x00000030 // mask of bits for transition states
  70. #define CD_MASK_STATE 0x00000007 // mask of bits for non-temp state
  71. #define CD_MASK_ALL 0x00000037 // mask of currently used bits
  72. #define REMOVE_LOCK_MAX_MINUTES 10 // ten minutes max time per io
  73. #define REMOVE_LOCK_HIGH_MARK 10000 // ten thousand concurrent ios?
  74. #define REDBOOK_REG_SUBKEY_NAME (L"DigitalAudio")
  75. #define REDBOOK_REG_CDDA_ACCURATE_KEY_NAME (L"CDDAAccurate")
  76. #define REDBOOK_REG_CDDA_SUPPORTED_KEY_NAME (L"CDDASupported")
  77. #define REDBOOK_REG_SECTORS_MASK_KEY_NAME (L"SectorsPerReadMask")
  78. #define REDBOOK_REG_SECTORS_KEY_NAME (L"SectorsPerRead")
  79. #define REDBOOK_REG_BUFFERS_KEY_NAME (L"NumberOfBuffers")
  80. #define REDBOOK_REG_VERSION_KEY_NAME (L"RegistryVersion")
  81. #define REDBOOK_MAX_CONSECUTIVE_ERRORS 10
  82. #define REDBOOK_WMI_BUFFERS_MAX 30 // must be at least 3 due to
  83. #define REDBOOK_WMI_BUFFERS_MIN 4 // method used to reduce stuttering
  84. #define REDBOOK_WMI_SECTORS_MAX 27 // 64k per read -- 1/3 sec.
  85. #define REDBOOK_WMI_SECTORS_MIN 1 // most processor-intensive
  86. #define REDBOOK_REG_VERSION 1
  87. //
  88. // A single sector from a CD is 2352 bytes
  89. //
  90. #define RAW_SECTOR_SIZE 2352
  91. #define COOKED_SECTOR_SIZE 2048
  92. //
  93. // these events are initialized to false, and are waited
  94. // upon by the system thread. synchronization events all
  95. //
  96. // order is important, as the thread will wait on either
  97. // events 0-3 _OR_ 1-4 to allow easy processing of
  98. // ioctls that require multiple state changes.
  99. //
  100. #define EVENT_IOCTL 0 // an ioctl, possibly state change
  101. #define EVENT_WMI 1 // a wmi request, possibly buffer size changes
  102. #define EVENT_DIGITAL 2 // digital reads/digital play
  103. #define EVENT_KILL_THREAD 3 // thread is about to die
  104. #define EVENT_COMPLETE 4 // complete processing of an ioctl
  105. #define EVENT_MAXIMUM 5 // how many events we have
  106. typedef struct _REDBOOK_STREAM_DATA
  107. *PREDBOOK_STREAM_DATA;
  108. typedef struct _REDBOOK_BUFFER_DATA
  109. *PREDBOOK_BUFFER_DATA;
  110. typedef struct _REDBOOK_CDROM_INFO
  111. *PREDBOOK_CDROM_INFO;
  112. typedef struct _REDBOOK_DEVICE_EXTENSION
  113. *PREDBOOK_DEVICE_EXTENSION;
  114. typedef struct _REDBOOK_COMPLETION_CONTEXT
  115. *PREDBOOK_COMPLETION_CONTEXT;
  116. //
  117. // Device Extension
  118. //
  119. typedef struct _REDBOOK_ERROR_LOG_DATA {
  120. LONG Count; // how many errors messages sent
  121. ULONG RCount[REDBOOK_ERR_MAXIMUM]; // count of each error
  122. } REDBOOK_ERROR_LOG_DATA, *PREDBOOK_ERROR_LOG_DATA;
  123. typedef struct _REDBOOK_STREAM_DATA {
  124. PFILE_OBJECT PinFileObject; // FileObject for pin
  125. PDEVICE_OBJECT PinDeviceObject;// DeviceObject for pin
  126. ULONG VolumeNodeId; // where is the device for this though?
  127. ULONG MixerPinId; // Pin of the mixer in sysaudio
  128. PFILE_OBJECT MixerFileObject;// keeps a reference to the object
  129. ULONG UpdateMixerPin; // PnpNotification arrived
  130. PVOID SysAudioReg; // For SysAudio PnpNotification
  131. //
  132. // the next two are win98's 'MY_PIN'
  133. // THESE TWO STRUCTS MUST BE KEPT CONTIGUOUS
  134. //
  135. struct {
  136. KSPIN_CONNECT Connect;
  137. KSDATAFORMAT_WAVEFORMATEX Format;
  138. };
  139. } REDBOOK_STREAM_DATA, *PREDBOOK_STREAM_DATA;
  140. //
  141. // move this struct's parts into REDBOOK_THREAD_DATA,
  142. // since nothing here should be accessed outside the thread
  143. //
  144. typedef struct _REDBOOK_CDROM_INFO {
  145. //
  146. // cache both Table of Contents and
  147. // number of times disc was changed
  148. // (CheckVerifyStatus)
  149. //
  150. PCDROM_TOC Toc;
  151. ULONG StateNow; // interlocked state, support routines to access
  152. ULONG CheckVerify;
  153. ULONG NextToRead; // next sector to read upon getting a free buffer
  154. ULONG NextToStream; // next sector to play when KS ready
  155. ULONG FinishedStreaming; // last to go through ks
  156. ULONG EndPlay; // last sector to read/play
  157. ULONG ReadErrors; // stop on errors
  158. ULONG StreamErrors; // stop on errors
  159. //
  160. // CDRom State
  161. //
  162. VOLUME_CONTROL Volume; // sizeof(char)*4
  163. } REDBOOK_CDROM_INFO, *PREDBOOK_CDROM_INFO;
  164. typedef struct _REDBOOK_BUFFER_DATA {
  165. PUCHAR SkipBuffer; // circular buffer
  166. PREDBOOK_COMPLETION_CONTEXT Contexts;
  167. PULONG ReadOk_X; // + inuse flag for completion routines
  168. PULONG StreamOk_X; // + to guarantee data integrity
  169. PUCHAR SilentBuffer; // when need to send silence
  170. PMDL SilentMdl; // when need to send silence
  171. ULONG IndexToRead;
  172. ULONG IndexToStream;
  173. union {
  174. struct {
  175. UCHAR MaxIrpStack; // allows cleaner IoInitializeIrp
  176. UCHAR Paused; // essentially a boolean
  177. UCHAR FirstPause; // so don't log pauses too often
  178. };
  179. ULONG Reserved1; // force alignment to ulong
  180. };
  181. } REDBOOK_BUFFER_DATA, *PREDBOOK_BUFFER_DATA;
  182. //
  183. // Read/Stream completion routine context(s)
  184. //
  185. #define REDBOOK_CC_READ 1
  186. #define REDBOOK_CC_STREAM 2
  187. #define REDBOOK_CC_READ_COMPLETE 3
  188. #define REDBOOK_CC_STREAM_COMPLETE 4
  189. typedef struct _REDBOOK_COMPLETION_CONTEXT {
  190. LIST_ENTRY ListEntry; // for queueing
  191. PREDBOOK_DEVICE_EXTENSION DeviceExtension;
  192. ULONG Reason; // REDBOOK_CC_*
  193. ULONG Index; // buffer index
  194. PUCHAR Buffer; // Buffer
  195. PMDL Mdl; // Mdl for buffer
  196. PIRP Irp; // Irp for buffer
  197. LARGE_INTEGER TimeReadReady; // time the buffer was ready to read into
  198. LARGE_INTEGER TimeReadSent; // time buffer was sent to read
  199. LARGE_INTEGER TimeStreamReady; // time the buffer was ready to stream
  200. LARGE_INTEGER TimeStreamSent; // time buffer was sent to stream
  201. KSSTREAM_HEADER Header; // have to be allocated, keep w/buffer
  202. } REDBOOK_COMPLETION_CONTEXT, *PREDBOOK_COMPLETION_CONTEXT;
  203. typedef struct _REDBOOK_THREAD_DATA {
  204. //
  205. // Handle to the thread
  206. //
  207. HANDLE SelfHandle;
  208. //
  209. // pointer to thread
  210. //
  211. PETHREAD SelfPointer;
  212. //
  213. // object pointer we referenced so we can safely wait for thread to exit
  214. //
  215. PKTHREAD ThreadReference;
  216. //
  217. // irp used to verify media hasn't changed
  218. //
  219. PIRP CheckVerifyIrp;
  220. //
  221. // Three queues: Ioctl, Wmi, Kill
  222. // Currently Processing is LIST_ENTRY pointer
  223. //
  224. LIST_ENTRY IoctlList; // dump ioctls here
  225. LIST_ENTRY WmiList; // dump wmi requests here
  226. LIST_ENTRY DigitalList; // dump rawread/stream requests here
  227. //
  228. // Three spinlocks: one for each queue
  229. //
  230. KSPIN_LOCK IoctlLock;
  231. KSPIN_LOCK WmiLock;
  232. KSPIN_LOCK DigitalLock;
  233. //
  234. // may need to wait for digital to complete for this
  235. //
  236. PLIST_ENTRY IoctlCurrent;
  237. //
  238. // keep count of pending io
  239. //
  240. ULONG PendingRead;
  241. ULONG PendingStream;
  242. //
  243. // Events for the thread
  244. //
  245. PKEVENT Events[EVENT_MAXIMUM];
  246. KWAIT_BLOCK EventBlock[EVENT_MAXIMUM];
  247. } REDBOOK_THREAD_DATA, *PREDBOOK_THREAD_DATA;
  248. // the kill event is just a list_entry
  249. typedef struct _REDBOOK_THREAD_IOCTL_DATA {
  250. LIST_ENTRY ListEntry;
  251. PIRP Irp;
  252. } REDBOOK_THREAD_IOCTL_DATA, *PREDBOOK_THREAD_IOCTL_DATA;
  253. typedef struct _REDBOOK_THREAD_WMI_DATA {
  254. LIST_ENTRY ListEntry;
  255. PIRP Irp;
  256. } REDBOOK_THREAD_WMI_DATA, *PREDBOOK_THREAD_WMI_DATA;
  257. #define SAVED_IO_MAX (1) // increase this for thread ioctl history
  258. typedef struct _SAVED_IO {
  259. union {
  260. struct {
  261. PIRP OriginalIrp; // see where it finished
  262. IRP IrpWithoutStack;
  263. IO_STACK_LOCATION Stack[8];
  264. };
  265. UCHAR Reserved[0x200]; // to make my tracing easier (real size: 0x194)
  266. };
  267. } SAVED_IO, *PSAVED_IO;
  268. //
  269. // Device Extension
  270. //
  271. typedef struct _REDBOOK_DEVICE_EXTENSION {
  272. //
  273. // Driver Object
  274. //
  275. PDRIVER_OBJECT DriverObject;
  276. //
  277. // Target Device Object
  278. //
  279. PDEVICE_OBJECT TargetDeviceObject;
  280. //
  281. // Target Physical Device Object
  282. //
  283. PDEVICE_OBJECT TargetPdo;
  284. //
  285. // Back pointer to device object
  286. //
  287. PDEVICE_OBJECT SelfDeviceObject;
  288. //
  289. // PagingPath Count
  290. //
  291. ULONG PagingPathCount;
  292. KEVENT PagingPathEvent;
  293. //
  294. // Pnp State
  295. //
  296. struct {
  297. UCHAR CurrentState;
  298. UCHAR PreviousState;
  299. BOOLEAN RemovePending;
  300. BOOLEAN Initialized;
  301. } Pnp;
  302. REDBOOK_ERROR_LOG_DATA ErrorLog;
  303. REDBOOK_CDROM_INFO CDRom;
  304. REDBOOK_BUFFER_DATA Buffer;
  305. REDBOOK_STREAM_DATA Stream;
  306. REDBOOK_THREAD_DATA Thread;
  307. //
  308. // WMI Information
  309. //
  310. REDBOOK_WMI_STD_DATA WmiData;
  311. REDBOOK_WMI_PERF_DATA WmiPerf;
  312. KSPIN_LOCK WmiPerfLock;
  313. WMILIB_CONTEXT WmiLibInfo;
  314. BOOLEAN WmiLibInitialized;
  315. //
  316. // Remove Lock -- Important while playing audio
  317. //
  318. IO_REMOVE_LOCK RemoveLock;
  319. ULONG SavedIoCurrentIndex;
  320. SAVED_IO SavedIo[SAVED_IO_MAX];
  321. } REDBOOK_DEVICE_EXTENSION, *PREDBOOK_DEVICE_EXTENSION;
  322. //
  323. // Driver Extension
  324. //
  325. typedef struct _REDBOOK_DRIVER_EXTENSION {
  326. UNICODE_STRING RegistryPath;
  327. } REDBOOK_DRIVER_EXTENSION, *PREDBOOK_DRIVER_EXTENSION;
  328. #define REDBOOK_DRIVER_EXTENSION_ID DriverEntry
  329. //
  330. // Macros to make life easy
  331. //
  332. #define LBA_TO_RELATIVE_MSF(Lba,Minutes,Seconds,Frames) \
  333. { \
  334. (Minutes) = (UCHAR)( ((Lba)+ 0) / (60 * 75) ); \
  335. (Seconds) = (UCHAR)((((Lba)+ 0) % (60 * 75)) / 75); \
  336. (Frames) = (UCHAR)((((Lba)+ 0) % (60 * 75)) % 75); \
  337. }
  338. #define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
  339. { \
  340. (Minutes) = (UCHAR)( ((Lba)+150) / (60 * 75) ); \
  341. (Seconds) = (UCHAR)((((Lba)+150) % (60 * 75)) / 75); \
  342. (Frames) = (UCHAR)((((Lba)+150) % (60 * 75)) % 75); \
  343. }
  344. #define MSF_TO_LBA(Minutes,Seconds,Frames) \
  345. (ULONG)(75*((60*(Minutes))+(Seconds))+(Frames) - 150)
  346. //
  347. // Algebraically equal to:
  348. // 75*60*Minutes +
  349. // 75*Seconds +
  350. // Frames - 150
  351. //
  352. #define MIN(_a,_b) (((_a) <= (_b)) ? (_a) : (_b))
  353. #define MAX(_a,_b) (((_a) >= (_b)) ? (_a) : (_b))
  354. //
  355. // neat little hacks to count number of bits set
  356. //
  357. __inline ULONG CountOfSetBits(ULONG _X)
  358. { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
  359. __inline ULONG CountOfSetBits32(ULONG32 _X)
  360. { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
  361. __inline ULONG CountOfSetBits64(ULONG64 _X)
  362. { ULONG i = 0; while (_X) { _X &= _X - 1; i++; } return i; }
  363. #define SET_FLAG(Flags, Bit) ((Flags) |= (Bit))
  364. #define CLEAR_FLAG(Flags, Bit) ((Flags) &= ~(Bit))
  365. #define TEST_FLAG(Flags, Bit) (((Flags) & (Bit)) != 0)
  366. #ifdef TRY
  367. #undef TRY
  368. #endif
  369. #ifdef LEAVE
  370. #undef LEAVE
  371. #endif
  372. #ifdef FINALLY
  373. #undef FINALLY
  374. #endif
  375. #define TRY
  376. #define LEAVE goto __label;
  377. #define FINALLY __label:
  378. #endif // __REDBOOK_H__