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.

266 lines
7.5 KiB

  1. #define DRIVER
  2. #define NTKERN
  3. #define _X86_
  4. #define WIN32
  5. #define DDK_VERSION 0x400
  6. #define IRP_MJ_WRITE 0x04
  7. #define CDECL
  8. #define FAR
  9. #define NEAR
  10. #define NTAPI __stdcall
  11. #include "wdm.h"
  12. #include "stdarg.h"
  13. #include "stdio.h"
  14. typedef ULONG BOOL;
  15. typedef LONG DWORD;
  16. typedef SHORT WORD;
  17. typedef NTSTATUS (NTAPI *PCREATEFILE) (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
  18. typedef NTSTATUS (NTAPI *PREFOBJECT) (HANDLE, ACCESS_MASK, POBJECT_TYPE, KPROCESSOR_MODE, PVOID *, POBJECT_HANDLE_INFORMATION);
  19. typedef PIRP (NTAPI *PREQUESTIRP) (ULONG, PDEVICE_OBJECT, PVOID, ULONG, PLARGE_INTEGER, PIO_STATUS_BLOCK);
  20. typedef NTSTATUS (FASTCALL *PCALLDRIVER) (PDEVICE_OBJECT, PIRP);
  21. typedef PDEVICE_OBJECT (NTAPI *PGETRELATED) (PFILE_OBJECT);
  22. typedef VOID (NTAPI *PDEREFOBJECT) (PVOID);
  23. typedef NTSTATUS (NTAPI *PCLOSEHANDLE) (HANDLE);
  24. typedef VOID (NTAPI *PQUEUEWORK) (PWORK_QUEUE_ITEM, WORK_QUEUE_TYPE);
  25. /* wave data block header */
  26. typedef struct wavehdr_tag {
  27. LPSTR lpData; /* pointer to locked data buffer */
  28. DWORD dwBufferLength; /* length of data buffer */
  29. DWORD dwBytesRecorded; /* used for input only */
  30. DWORD dwUser; /* for client's use */
  31. DWORD dwFlags; /* assorted flags (see defines) */
  32. DWORD dwLoops; /* loop control counter */
  33. struct wavehdr_tag FAR *lpNext; /* reserved for driver */
  34. DWORD reserved; /* reserved for driver */
  35. } WAVEHDR, *PWAVEHDR, NEAR *NPWAVEHDR, FAR *LPWAVEHDR;
  36. #include <ks.h>
  37. #include <ksmedia.h>
  38. typedef NTSTATUS (NTAPI *PCREATEPIN) (HANDLE, PKSPIN_CONNECT, HANDLE);
  39. typedef struct _myConnect {
  40. KSPIN_CONNECT;
  41. KSDATARANGE_AUDIO;
  42. } MY_PIN;
  43. const CDECL GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
  44. const CDECL GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
  45. const CDECL GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00};
  46. const CDECL GUID KSPROPSETID_Control = {0x1D58C920L, 0xAC9B, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00};
  47. const CDECL GUID KSDATAFORMAT_FORMAT_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a};
  48. const CDECL GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00};
  49. NTSTATUS PM_Callback(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
  50. VOID ClosePin(VOID);
  51. HANDLE hMixerSink = NULL;
  52. HANDLE hMixer = NULL;
  53. MY_PIN pin;
  54. BOOL MixerRunning = FALSE;
  55. USHORT DeviceString[] = L"\\DosDevices\\KMIXER";
  56. UNICODE_STRING UnicodeDeviceString = { 0, sizeof(DeviceString), DeviceString };
  57. OBJECT_ATTRIBUTES ObjectAttributes = {sizeof(OBJECT_ATTRIBUTES),
  58. NULL,
  59. &UnicodeDeviceString,
  60. 0,
  61. NULL,
  62. NULL };
  63. IO_STATUS_BLOCK IoStatusBlock;
  64. PREQUESTIRP pRequest;
  65. PCALLDRIVER pCallDriver;
  66. PDEVICE_OBJECT pDeviceObject;
  67. PFILE_OBJECT pFileObject = NULL;
  68. HANDLE hNtosModule = NULL;
  69. HANDLE hKsModule = NULL;
  70. PQUEUEWORK pQueueWork;
  71. VOID
  72. OpenPin(VOID)
  73. {
  74. PCREATEPIN pCreatePin;
  75. PCREATEFILE pCreateFile;
  76. NTSTATUS Status;
  77. PREFOBJECT pRefObject;
  78. PGETRELATED pGetRelated;
  79. /* We only support one mixer client through our VxD at a time */
  80. if (MixerRunning)
  81. {
  82. _asm int 3
  83. return;
  84. }
  85. ObjectAttributes.ObjectName->Length = sizeof(DeviceString) - 2;
  86. /* Get entry points for all the WDM functions we will use */
  87. pCreateFile = (PCREATEFILE) _PELDR_GetProcAddress("ntoskrnl.exe","ZwCreateFile",NULL);
  88. pCreatePin = (PCREATEPIN) _PELDR_GetProcAddress("ks.sys","KsCreatePin",NULL);
  89. pRefObject = (PREFOBJECT) _PELDR_GetProcAddress("ntoskrnl.exe","ObReferenceObjectByHandle",NULL);
  90. pGetRelated = (PGETRELATED) _PELDR_GetProcAddress("ntoskrnl.exe","IoGetRelatedDeviceObject",NULL);
  91. pRequest = (PREQUESTIRP) _PELDR_GetProcAddress("ntoskrnl.exe","IoBuildAsynchronousFsdRequest",NULL);
  92. pCallDriver = (PCALLDRIVER) _PELDR_GetProcAddress("ntoskrnl.exe","IofCallDriver",NULL);
  93. pQueueWork = (PQUEUEWORK) _PELDR_GetProcAddress("ntoskrnl.exe","ExQueueWorkItem",NULL);
  94. if (!pCreateFile || !pCreatePin || !pRefObject || !pGetRelated || !pRequest || !pCallDriver || !pQueueWork)
  95. {
  96. _asm int 3
  97. ClosePin();
  98. return;
  99. }
  100. /* Open the mixer */
  101. (*pCreateFile) (&hMixer,
  102. GENERIC_READ | GENERIC_WRITE,
  103. &ObjectAttributes,
  104. &IoStatusBlock,
  105. NULL,
  106. FILE_ATTRIBUTE_NORMAL,
  107. 0,
  108. FILE_OPEN,
  109. 0,
  110. NULL,
  111. 0);
  112. if (hMixer == NULL)
  113. {
  114. _asm int 3
  115. ClosePin();
  116. return;
  117. }
  118. /* We connect to the KMIXER SINK */
  119. pin.PinId = 1; // KMIXER SINK
  120. pin.PinToHandle = NULL; // no "connect to"
  121. pin.Interface.Set = KSINTERFACESETID_Standard;
  122. pin.Interface.Id = KSINTERFACE_STANDARD_WAVE_QUEUED;
  123. pin.Medium.Set = KSMEDIUMSETID_Standard;
  124. pin.Medium.Id = KSMEDIUM_STANDARD_DEVIO;
  125. pin.Priority.PriorityClass = KSPRIORITY_NORMAL;
  126. pin.Priority.PrioritySubClass = 0;
  127. pin.DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
  128. pin.DataRange.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
  129. pin.DataRange.Specifier = KSDATAFORMAT_FORMAT_WAVEFORMATEX;
  130. pin.DataRange.FormatSize = sizeof( KSDATARANGE_AUDIO );
  131. pin.MaximumChannels = 2;
  132. pin.MinimumSampleFrequency = 44000;
  133. pin.MaximumSampleFrequency = 44000;
  134. pin.MinimumBitsPerSample = 16;
  135. pin.MaximumBitsPerSample = 16;
  136. /* Open a pin */
  137. Status = (*pCreatePin) ( hMixer, (PKSPIN_CONNECT) &pin, &hMixerSink );
  138. if (!NT_SUCCESS(Status))
  139. {
  140. _asm int 3
  141. ClosePin();
  142. return;
  143. }
  144. /* Reference the file object for this pin */
  145. Status = (*pRefObject) (hMixerSink, FILE_WRITE_DATA, NULL, KernelMode, &pFileObject, NULL);
  146. if (!NT_SUCCESS(Status))
  147. {
  148. _asm int 3
  149. ClosePin();
  150. return;
  151. }
  152. /* Get the related device object for this pin */
  153. pDeviceObject = (PVOID) (*pGetRelated) (pFileObject);
  154. MixerRunning = TRUE;
  155. return;
  156. }
  157. VOID
  158. ClosePin(VOID)
  159. {
  160. PDEREFOBJECT pDeRefObject;
  161. PCLOSEHANDLE pClose;
  162. /* This is designed to bring us back to square one, even if we were not completely opened */
  163. MixerRunning = FALSE;
  164. /* First, close the file object (pFileObject, if it exists) */
  165. if (pFileObject)
  166. {
  167. /* De-reference the file object */
  168. pDeRefObject = (PDEREFOBJECT) _PELDR_GetProcAddress("ntoskrnl.exe","ObDereferenceObject",NULL);
  169. if (!pDeRefObject)
  170. {
  171. _asm int 3
  172. }
  173. else
  174. (*pDeRefObject) (pFileObject);
  175. pFileObject = NULL;
  176. }
  177. /* Next, close the pin handle (hMixerSink, if it exists) */
  178. if (hMixerSink)
  179. {
  180. pClose = (PCLOSEHANDLE) _PELDR_GetProcAddress("ntoskrnl.exe","ZwClose",NULL);
  181. if (!pClose)
  182. {
  183. _asm int 3
  184. }
  185. else
  186. (*pClose) (hMixerSink);
  187. hMixerSink = NULL;
  188. }
  189. /* Finally, close the KMIXER handle (hMixer, if it exists) */
  190. if (hMixer)
  191. {
  192. pClose = (PCLOSEHANDLE) _PELDR_GetProcAddress("ntoskrnl.exe","ZwClose",NULL);
  193. if (!pClose)
  194. {
  195. _asm int 3
  196. }
  197. else
  198. (*pClose) (hMixer);
  199. hMixer = NULL;
  200. }
  201. return;
  202. }
  203. VOID
  204. WritePin(LPWAVEHDR pData, PVOID pMyCallback, PVOID RefData)
  205. {
  206. KSSTATE DeviceState = KSSTATE_RUN;
  207. PIRP pIrp = NULL;
  208. PIO_STACK_LOCATION pIrpStack;
  209. if (!MixerRunning)
  210. {
  211. _asm int 3
  212. return;
  213. }
  214. pIrp = (*pRequest) (IRP_MJ_WRITE, pDeviceObject, (PVOID)pData, sizeof(WAVEHDR), 0, NULL);
  215. if (!pIrp)
  216. {
  217. _asm int 3
  218. return;
  219. }
  220. pIrpStack = IoGetNextIrpStackLocation(pIrp);
  221. pIrpStack->FileObject = pFileObject;
  222. IoSetCompletionRoutine(pIrp, pMyCallback, RefData, TRUE, TRUE, TRUE);
  223. (*pCallDriver) ( pDeviceObject, pIrp );
  224. return;
  225. }