10 MIXER_CONTEXT MixerContext
;
11 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
13 PVOID
Alloc(ULONG NumBytes
)
15 //printf("Alloc: %lu\n", NumBytes);
16 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, NumBytes
);
22 //printf("Close: Handle %p\n", hDevice);
23 if (CloseHandle(hDevice
))
24 return MM_STATUS_SUCCESS
;
26 return MM_STATUS_UNSUCCESSFUL
;
32 //printf("Free: %p\n", Block);
33 HeapFree(GetProcessHeap(), 0, Block
);
37 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
39 //printf("Copy: Src %p Dst %p NumBytes %lu\n", Src, Dst, NumBytes);
40 CopyMemory(Src
, Dst
, NumBytes
);
48 DevicePath
[1] = L
'\\';
49 *hDevice
= CreateFileW(DevicePath
,
50 GENERIC_READ
| GENERIC_WRITE
,
56 if (*hDevice
== INVALID_HANDLE_VALUE
)
58 //wprintf(L" Failed to open %s Error %lu\n", DevicePath, GetLastError());
59 return MM_STATUS_UNSUCCESSFUL
;
61 wprintf(L
"Open: %s hDevice %p\n", DevicePath
, *hDevice
);
63 return MM_STATUS_SUCCESS
;
69 IN ULONG dwIoControlCode
,
71 IN ULONG nInBufferSize
,
72 OUT PVOID lpOutBuffer
,
74 PULONG lpBytesReturned
)
76 OVERLAPPED Overlapped
;
78 DWORD Transferred
= 0;
80 //printf("hMixer %p dwIoControlCode %lx lpInBuffer %p nInBufferSize %lu lpOutBuffer %p nOutBufferSize %lu lpBytesReturned %p\n",
81 // hMixer, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
83 /* Overlapped I/O is done here - this is used for waiting for completion */
84 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
85 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
87 if ( ! Overlapped
.hEvent
)
88 return MM_STATUS_NO_MEMORY
;
90 /* Talk to the device */
91 IoResult
= DeviceIoControl(hMixer
,
100 /* If failure occurs, make sure it's not just due to the overlapped I/O */
103 if ( GetLastError() != ERROR_IO_PENDING
)
105 CloseHandle(Overlapped
.hEvent
);
107 //printf("Control: Failed with %lu Transferred %lu\n", GetLastError(), Transferred);
109 if (GetLastError() == ERROR_MORE_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
111 if ( lpBytesReturned
)
112 *lpBytesReturned
= Transferred
;
113 return MM_STATUS_MORE_ENTRIES
;
116 return MM_STATUS_UNSUCCESSFUL
;
120 /* Wait for the I/O to complete */
121 IoResult
= GetOverlappedResult(hMixer
,
126 /* Don't need this any more */
127 CloseHandle(Overlapped
.hEvent
);
130 return MM_STATUS_UNSUCCESSFUL
;
132 //printf("Transferred %lu bytes in Sync overlapped I/O\n", Transferred);
134 if ( lpBytesReturned
)
135 *lpBytesReturned
= Transferred
;
137 return MM_STATUS_SUCCESS
;
142 IN PVOID EnumContext
,
143 IN ULONG DeviceIndex
,
144 OUT LPWSTR
* DeviceName
,
145 OUT PHANDLE OutHandle
,
148 SP_DEVICE_INTERFACE_DATA InterfaceData
;
149 SP_DEVINFO_DATA DeviceData
;
150 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData
;
155 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
157 InterfaceData
.cbSize
= sizeof(InterfaceData
);
158 InterfaceData
.Reserved
= 0;
160 Result
= SetupDiEnumDeviceInterfaces(EnumContext
,
168 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
170 printf("LastDevice\n");
171 return MM_STATUS_NO_MORE_DEVICES
;
173 printf("SetupDiEnumDeviceInterfaces failed with %lu\n", GetLastError());
174 return MM_STATUS_UNSUCCESSFUL
;
177 Length
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) + MAX_PATH
* sizeof(WCHAR
);
178 DetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(),
181 DetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
182 DeviceData
.cbSize
= sizeof(DeviceData
);
183 DeviceData
.Reserved
= 0;
185 Result
= SetupDiGetDeviceInterfaceDetailW(EnumContext
,
194 printf("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
195 return MM_STATUS_UNSUCCESSFUL
;
199 *OutKey
= SetupDiOpenDeviceInterfaceRegKey(EnumContext
, &InterfaceData
, 0, KEY_READ
);
200 if ((HKEY
)*OutKey
== INVALID_HANDLE_VALUE
)
202 HeapFree(GetProcessHeap(), 0, DetailData
);
203 return MM_STATUS_UNSUCCESSFUL
;
206 Status
= Open(DetailData
->DevicePath
, OutHandle
);
208 if (Status
!= MM_STATUS_SUCCESS
)
210 RegCloseKey((HKEY
)*OutKey
);
211 HeapFree(GetProcessHeap(), 0, DetailData
);
215 *DeviceName
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData
->DevicePath
)+1) * sizeof(WCHAR
));
216 if (*DeviceName
== NULL
)
218 CloseHandle(*OutHandle
);
219 RegCloseKey((HKEY
)*OutKey
);
220 HeapFree(GetProcessHeap(), 0, DetailData
);
221 return MM_STATUS_NO_MEMORY
;
224 wcscpy(*DeviceName
, DetailData
->DevicePath
);
225 HeapFree(GetProcessHeap(), 0, DetailData
);
234 OUT PVOID
* ResultBuffer
,
235 OUT PULONG ResultLength
,
238 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, NULL
, ResultLength
) == ERROR_FILE_NOT_FOUND
)
239 return MM_STATUS_UNSUCCESSFUL
;
241 *ResultBuffer
= HeapAlloc(GetProcessHeap(), 0, *ResultLength
);
242 if (*ResultBuffer
== NULL
)
243 return MM_STATUS_NO_MEMORY
;
245 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, *ResultBuffer
, ResultLength
) != ERROR_SUCCESS
)
247 HeapFree(GetProcessHeap(), 0, *ResultBuffer
);
248 return MM_STATUS_UNSUCCESSFUL
;
250 return MM_STATUS_SUCCESS
;
257 IN ULONG DesiredAccess
,
260 if (RegOpenKeyExW((HKEY
)hKey
, SubKey
, 0, DesiredAccess
, (PHKEY
)OutKey
) == ERROR_SUCCESS
)
261 return MM_STATUS_SUCCESS
;
263 return MM_STATUS_UNSUCCESSFUL
;
270 RegCloseKey((HKEY
)hKey
);
271 return MM_STATUS_SUCCESS
;
275 int main(int argc
, char**argv
)
278 HDEVINFO DeviceHandle
;
279 MIXERCAPSW MixCaps1
, MixCaps2
;
280 ULONG Index
, SubIndex
;
283 MIXERLINEW MixerLine1
, MixerLine2
;
284 MIXERLINECONTROLS Controls1
, Controls2
;
286 ZeroMemory(&MixerContext
, sizeof(MIXER_CONTEXT
));
288 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
291 DIGCF_DEVICEINTERFACE
|DIGCF_PRESENT
);
292 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
294 printf("SetupDiGetClassDevs failed with %lx\n", GetLastError());
298 printf("DeviceHandle %p\n", DeviceHandle
);
300 MixerContext
.SizeOfStruct
= sizeof(MIXER_CONTEXT
);
301 MixerContext
.Alloc
= Alloc
;
302 MixerContext
.Close
= Close
;
303 MixerContext
.Control
= Control
;
304 MixerContext
.Copy
= Copy
;
305 MixerContext
.Free
= Free
;
306 MixerContext
.Open
= Open
;
307 MixerContext
.OpenKey
= OpenKey
;
308 MixerContext
.CloseKey
= CloseKey
;
309 MixerContext
.QueryKeyValue
= QueryKeyValue
;
311 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
313 printf("Status %x\n", Status
);
314 printf("NumberOfMixers %lu mixerGetNumDevs %u\n", MMixerGetCount(&MixerContext
), mixerGetNumDevs());
316 for(Index
= 0; Index
< MMixerGetCount(&MixerContext
); Index
++)
318 mixerGetDevCapsW(Index
, &MixCaps1
, sizeof(MIXERCAPSW
));
319 wprintf(L
"WINM: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps1
.cDestinations
, MixCaps1
.fdwSupport
, MixCaps1
.szPname
, MixCaps1
.vDriverVersion
, MixCaps1
.wMid
, MixCaps1
.wPid
);
320 MMixerGetCapabilities(&MixerContext
, Index
, &MixCaps2
);
321 wprintf(L
"MMIX: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps2
.cDestinations
, MixCaps2
.fdwSupport
, MixCaps2
.szPname
, MixCaps2
.vDriverVersion
, MixCaps2
.wMid
, MixCaps2
.wPid
);
323 mixerOpen(&hMixer1
, Index
, 0, 0, MIXER_OBJECTF_HMIXER
);
324 MMixerOpen(&MixerContext
, Index
, NULL
, NULL
, &hMixer2
);
326 ZeroMemory(&MixerLine1
, sizeof(MIXERLINEW
));
327 ZeroMemory(&MixerLine2
, sizeof(MIXERLINEW
));
328 MixerLine1
.cbStruct
= sizeof(MIXERLINEW
);
329 MixerLine2
.cbStruct
= sizeof(MIXERLINEW
);
330 mixerGetLineInfoW((HMIXEROBJ
)hMixer1
, &MixerLine1
, MIXER_GETLINEINFOF_DESTINATION
);
331 MMixerGetLineInfo(&MixerContext
, hMixer2
, MIXER_GETLINEINFOF_DESTINATION
, &MixerLine2
);
333 wprintf(L
"WINM: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
334 MixerLine1
.dwDestination
, MixerLine1
.dwSource
, MixerLine1
.dwLineID
, MixerLine1
.dwUser
, MixerLine1
.dwComponentType
, MixerLine1
.cChannels
, MixerLine1
.cConnections
, MixerLine1
.cControls
, MixerLine1
.szShortName
, MixerLine1
.szName
);
336 wprintf(L
"MMIX: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
337 MixerLine2
.dwDestination
, MixerLine2
.dwSource
, MixerLine2
.dwLineID
, MixerLine2
.dwUser
, MixerLine2
.dwComponentType
, MixerLine2
.cChannels
, MixerLine2
.cConnections
, MixerLine2
.cControls
, MixerLine2
.szShortName
, MixerLine2
.szName
);
339 Controls1
.cbStruct
= sizeof(MIXERLINECONTROLS
);
340 Controls2
.cbStruct
= sizeof(MIXERLINECONTROLS
);
342 Controls1
.cbmxctrl
= sizeof(MIXERCONTROL
);
343 Controls2
.cbmxctrl
= sizeof(MIXERCONTROL
);
345 Controls1
.cControls
= MixerLine1
.cControls
;
346 Controls2
.cControls
= MixerLine2
.cControls
;
348 Controls1
.dwLineID
= MixerLine1
.dwLineID
;
349 Controls2
.dwLineID
= MixerLine2
.dwLineID
;
353 Controls1
.pamxctrl
= (LPMIXERCONTROL
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MIXERCONTROL
) * Controls1
.cControls
);
354 Controls2
.pamxctrl
= (LPMIXERCONTROL
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(MIXERCONTROL
) * Controls2
.cControls
);
356 for(SubIndex
= 0; SubIndex
< Controls1
.cControls
; SubIndex
++)
357 Controls1
.pamxctrl
[SubIndex
].cbStruct
= sizeof(MIXERCONTROL
);
359 for(SubIndex
= 0; SubIndex
< Controls2
.cControls
; SubIndex
++)
360 Controls2
.pamxctrl
[SubIndex
].cbStruct
= sizeof(MIXERCONTROL
);
362 mixerGetLineControls((HMIXEROBJ
)hMixer1
, &Controls1
, MIXER_GETLINECONTROLSF_ALL
);
364 wprintf(L
"----------------------------------------\n");
365 for(SubIndex
= 0; SubIndex
< Controls1
.cControls
; SubIndex
++)
367 wprintf(L
"WINM: Index %d dwControlID %lx dwControlType %lx fdwControl %lx cMultipleItems %lx szName %s szShortName %s \n", SubIndex
, Controls1
.pamxctrl
[SubIndex
].dwControlID
, Controls1
.pamxctrl
[SubIndex
].dwControlType
, Controls1
.pamxctrl
[SubIndex
].fdwControl
, Controls1
.pamxctrl
[SubIndex
].cMultipleItems
, Controls1
.pamxctrl
[SubIndex
].szName
, Controls1
.pamxctrl
[SubIndex
].szShortName
);
369 wprintf(L
"----------------------------------------\n");
372 wprintf(L
"=======================\n");