Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
2b69540e
Commit
2b69540e
authored
Oct 06, 2020
by
Andrew Eikum
Committed by
Alexandre Julliard
Oct 06, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mmdevapi: Implement ActivateAudioInterfaceAsync.
Signed-off-by:
Andrew Eikum
<
aeikum@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
d5891996
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
393 additions
and
0 deletions
+393
-0
main.c
dlls/mmdevapi/main.c
+165
-0
mmdevapi.spec
dlls/mmdevapi/mmdevapi.spec
+2
-0
mmdevenum.c
dlls/mmdevapi/tests/mmdevenum.c
+190
-0
mmdeviceapi.idl
include/mmdeviceapi.idl
+36
-0
No files found.
dlls/mmdevapi/main.c
View file @
2b69540e
...
...
@@ -319,3 +319,168 @@ HRESULT WINAPI DllUnregisterServer(void)
{
return
__wine_unregister_resources
(
instance
);
}
struct
activate_async_op
{
IActivateAudioInterfaceAsyncOperation
IActivateAudioInterfaceAsyncOperation_iface
;
LONG
ref
;
IActivateAudioInterfaceCompletionHandler
*
callback
;
HRESULT
result_hr
;
IUnknown
*
result_iface
;
};
static
struct
activate_async_op
*
impl_from_IActivateAudioInterfaceAsyncOperation
(
IActivateAudioInterfaceAsyncOperation
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
activate_async_op
,
IActivateAudioInterfaceAsyncOperation_iface
);
}
static
HRESULT
WINAPI
activate_async_op_QueryInterface
(
IActivateAudioInterfaceAsyncOperation
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
struct
activate_async_op
*
This
=
impl_from_IActivateAudioInterfaceAsyncOperation
(
iface
);
TRACE
(
"(%p)->(%s, %p)
\n
"
,
This
,
debugstr_guid
(
riid
),
ppv
);
if
(
!
ppv
)
return
E_POINTER
;
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IActivateAudioInterfaceAsyncOperation
))
{
*
ppv
=
&
This
->
IActivateAudioInterfaceAsyncOperation_iface
;
}
else
{
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
IUnknown_AddRef
((
IUnknown
*
)
*
ppv
);
return
S_OK
;
}
static
ULONG
WINAPI
activate_async_op_AddRef
(
IActivateAudioInterfaceAsyncOperation
*
iface
)
{
struct
activate_async_op
*
This
=
impl_from_IActivateAudioInterfaceAsyncOperation
(
iface
);
LONG
ref
=
InterlockedIncrement
(
&
This
->
ref
);
TRACE
(
"(%p) refcount now %i
\n
"
,
This
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
activate_async_op_Release
(
IActivateAudioInterfaceAsyncOperation
*
iface
)
{
struct
activate_async_op
*
This
=
impl_from_IActivateAudioInterfaceAsyncOperation
(
iface
);
LONG
ref
=
InterlockedDecrement
(
&
This
->
ref
);
TRACE
(
"(%p) refcount now %i
\n
"
,
This
,
ref
);
if
(
!
ref
)
{
if
(
This
->
result_iface
)
IUnknown_Release
(
This
->
result_iface
);
IActivateAudioInterfaceCompletionHandler_Release
(
This
->
callback
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
}
return
ref
;
}
static
HRESULT
WINAPI
activate_async_op_GetActivateResult
(
IActivateAudioInterfaceAsyncOperation
*
iface
,
HRESULT
*
result_hr
,
IUnknown
**
result_iface
)
{
struct
activate_async_op
*
This
=
impl_from_IActivateAudioInterfaceAsyncOperation
(
iface
);
TRACE
(
"(%p)->(%p, %p)
\n
"
,
This
,
result_hr
,
result_iface
);
*
result_hr
=
This
->
result_hr
;
if
(
This
->
result_hr
==
S_OK
){
*
result_iface
=
This
->
result_iface
;
IUnknown_AddRef
(
*
result_iface
);
}
return
S_OK
;
}
static
IActivateAudioInterfaceAsyncOperationVtbl
IActivateAudioInterfaceAsyncOperation_vtbl
=
{
activate_async_op_QueryInterface
,
activate_async_op_AddRef
,
activate_async_op_Release
,
activate_async_op_GetActivateResult
,
};
static
DWORD
WINAPI
activate_async_threadproc
(
void
*
user
)
{
struct
activate_async_op
*
op
=
user
;
IActivateAudioInterfaceCompletionHandler_ActivateCompleted
(
op
->
callback
,
&
op
->
IActivateAudioInterfaceAsyncOperation_iface
);
IActivateAudioInterfaceAsyncOperation_Release
(
&
op
->
IActivateAudioInterfaceAsyncOperation_iface
);
return
0
;
}
static
HRESULT
get_mmdevice_by_activatepath
(
const
WCHAR
*
path
,
IMMDevice
**
mmdev
)
{
IMMDeviceEnumerator
*
devenum
;
HRESULT
hr
;
static
const
WCHAR
DEVINTERFACE_AUDIO_RENDER_WSTR
[]
=
L"{E6327CAD-DCEC-4949-AE8A-991E976A79D2}"
;
static
const
WCHAR
DEVINTERFACE_AUDIO_CAPTURE_WSTR
[]
=
L"{2EEF81BE-33FA-4800-9670-1CD474972C3F}"
;
hr
=
MMDevEnum_Create
(
&
IID_IMMDeviceEnumerator
,
(
void
**
)
&
devenum
);
if
(
FAILED
(
hr
))
{
WARN
(
"Failed to create MMDeviceEnumerator: %08x
\n
"
,
hr
);
return
hr
;
}
if
(
!
lstrcmpiW
(
path
,
DEVINTERFACE_AUDIO_RENDER_WSTR
)){
hr
=
IMMDeviceEnumerator_GetDefaultAudioEndpoint
(
devenum
,
eRender
,
eMultimedia
,
mmdev
);
}
else
if
(
!
lstrcmpiW
(
path
,
DEVINTERFACE_AUDIO_CAPTURE_WSTR
)){
hr
=
IMMDeviceEnumerator_GetDefaultAudioEndpoint
(
devenum
,
eCapture
,
eMultimedia
,
mmdev
);
}
else
{
FIXME
(
"How to map path to device id? %s
\n
"
,
debugstr_w
(
path
));
hr
=
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
);
}
if
(
FAILED
(
hr
))
{
WARN
(
"Failed to get requested device (%s): %08x
\n
"
,
debugstr_w
(
path
),
hr
);
*
mmdev
=
NULL
;
hr
=
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
);
}
IMMDeviceEnumerator_Release
(
devenum
);
return
hr
;
}
/***********************************************************************
* ActivateAudioInterfaceAsync (MMDEVAPI.17)
*/
HRESULT
WINAPI
ActivateAudioInterfaceAsync
(
const
WCHAR
*
path
,
REFIID
riid
,
PROPVARIANT
*
params
,
IActivateAudioInterfaceCompletionHandler
*
done_handler
,
IActivateAudioInterfaceAsyncOperation
**
op_out
)
{
struct
activate_async_op
*
op
;
HANDLE
ht
;
IMMDevice
*
mmdev
;
TRACE
(
"(%s, %s, %p, %p, %p)
\n
"
,
debugstr_w
(
path
),
debugstr_guid
(
riid
),
params
,
done_handler
,
op_out
);
op
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
op
));
if
(
!
op
)
return
E_OUTOFMEMORY
;
op
->
ref
=
2
;
/* returned ref and threadproc ref */
op
->
IActivateAudioInterfaceAsyncOperation_iface
.
lpVtbl
=
&
IActivateAudioInterfaceAsyncOperation_vtbl
;
op
->
callback
=
done_handler
;
IActivateAudioInterfaceCompletionHandler_AddRef
(
done_handler
);
op
->
result_hr
=
get_mmdevice_by_activatepath
(
path
,
&
mmdev
);
if
(
SUCCEEDED
(
op
->
result_hr
))
{
op
->
result_hr
=
IMMDevice_Activate
(
mmdev
,
riid
,
CLSCTX_INPROC_SERVER
,
params
,
(
void
**
)
&
op
->
result_iface
);
IMMDevice_Release
(
mmdev
);
}
else
op
->
result_iface
=
NULL
;
ht
=
CreateThread
(
NULL
,
0
,
&
activate_async_threadproc
,
op
,
0
,
NULL
);
CloseHandle
(
ht
);
*
op_out
=
&
op
->
IActivateAudioInterfaceAsyncOperation_iface
;
return
S_OK
;
}
dlls/mmdevapi/mmdevapi.spec
View file @
2b69540e
...
...
@@ -12,6 +12,8 @@
13 stub @
14 stub @
15 stub @
16 stub @
17 stdcall ActivateAudioInterfaceAsync( wstr ptr ptr ptr ptr )
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject( ptr ptr ptr )
...
...
dlls/mmdevapi/tests/mmdevenum.c
View file @
2b69540e
...
...
@@ -31,6 +31,9 @@
DEFINE_GUID
(
GUID_NULL
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
);
static
UINT
g_num_mmdevs
;
static
WCHAR
g_device_path
[
MAX_PATH
];
/* Some of the QueryInterface tests are really just to check if I got the IIDs right :) */
/* IMMDeviceCollection appears to have no QueryInterface method and instead forwards to mme */
...
...
@@ -85,6 +88,8 @@ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
ok
(
hr
==
E_INVALIDARG
,
"Asking for too high device returned 0x%08x
\n
"
,
hr
);
ok
(
dev
==
NULL
,
"Returned non-null device
\n
"
);
g_num_mmdevs
=
numdev
;
if
(
numdev
)
{
hr
=
IMMDeviceCollection_Item
(
col
,
0
,
NULL
);
...
...
@@ -101,6 +106,7 @@ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
{
IMMDevice
*
dev2
;
lstrcpyW
(
g_device_path
,
id
);
temp
[
sizeof
(
temp
)
-
1
]
=
0
;
WideCharToMultiByte
(
CP_ACP
,
0
,
id
,
-
1
,
temp
,
sizeof
(
temp
)
-
1
,
NULL
,
NULL
);
trace
(
"Device found: %s
\n
"
,
temp
);
...
...
@@ -119,6 +125,188 @@ static void test_collection(IMMDeviceEnumerator *mme, IMMDeviceCollection *col)
IMMDeviceCollection_Release
(
col
);
}
static
struct
{
LONG
ref
;
HANDLE
evt
;
CRITICAL_SECTION
lock
;
IActivateAudioInterfaceAsyncOperation
*
op
;
DWORD
main_tid
;
char
msg_pfx
[
128
];
IUnknown
*
result_iface
;
HRESULT
result_hr
;
}
async_activate_test
;
static
HRESULT
WINAPI
async_activate_QueryInterface
(
IActivateAudioInterfaceCompletionHandler
*
iface
,
REFIID
riid
,
void
**
ppvObject
)
{
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IAgileObject
)
||
IsEqualIID
(
riid
,
&
IID_IActivateAudioInterfaceCompletionHandler
)){
*
ppvObject
=
iface
;
IUnknown_AddRef
((
IUnknown
*
)
*
ppvObject
);
return
S_OK
;
}
*
ppvObject
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
async_activate_AddRef
(
IActivateAudioInterfaceCompletionHandler
*
iface
)
{
return
InterlockedIncrement
(
&
async_activate_test
.
ref
);
}
static
ULONG
WINAPI
async_activate_Release
(
IActivateAudioInterfaceCompletionHandler
*
iface
)
{
ULONG
ref
=
InterlockedDecrement
(
&
async_activate_test
.
ref
);
if
(
ref
==
1
)
SetEvent
(
async_activate_test
.
evt
);
return
ref
;
}
static
HRESULT
WINAPI
async_activate_ActivateCompleted
(
IActivateAudioInterfaceCompletionHandler
*
iface
,
IActivateAudioInterfaceAsyncOperation
*
op
)
{
HRESULT
hr
;
EnterCriticalSection
(
&
async_activate_test
.
lock
);
ok
(
op
==
async_activate_test
.
op
,
"%s: Got different completion operation
\n
"
,
async_activate_test
.
msg_pfx
);
LeaveCriticalSection
(
&
async_activate_test
.
lock
);
ok
(
GetCurrentThreadId
()
!=
async_activate_test
.
main_tid
,
"%s: Expected callback on worker thread
\n
"
,
async_activate_test
.
msg_pfx
);
hr
=
IActivateAudioInterfaceAsyncOperation_GetActivateResult
(
op
,
&
async_activate_test
.
result_hr
,
&
async_activate_test
.
result_iface
);
ok
(
hr
==
S_OK
,
"%s: GetActivateResult failed: %08x
\n
"
,
async_activate_test
.
msg_pfx
,
hr
);
return
S_OK
;
}
static
IActivateAudioInterfaceCompletionHandlerVtbl
async_activate_vtbl
=
{
async_activate_QueryInterface
,
async_activate_AddRef
,
async_activate_Release
,
async_activate_ActivateCompleted
,
};
static
IActivateAudioInterfaceCompletionHandler
async_activate_done
=
{
&
async_activate_vtbl
};
static
void
test_ActivateAudioInterfaceAsync
(
void
)
{
HRESULT
(
*
WINAPI
pActivateAudioInterfaceAsync
)(
const
WCHAR
*
path
,
REFIID
riid
,
PROPVARIANT
*
params
,
IActivateAudioInterfaceCompletionHandler
*
done_handler
,
IActivateAudioInterfaceAsyncOperation
**
op
);
HANDLE
h_mmdev
;
HRESULT
hr
;
LPOLESTR
path
;
DWORD
dr
;
IAudioClient3
*
ac3
;
h_mmdev
=
LoadLibraryA
(
"mmdevapi.dll"
);
/* some applications look this up by ordinal */
pActivateAudioInterfaceAsync
=
(
void
*
)
GetProcAddress
(
h_mmdev
,
(
char
*
)
17
);
ok
(
pActivateAudioInterfaceAsync
!=
NULL
,
"mmdevapi.ActivateAudioInterfaceAsync missing!
\n
"
);
async_activate_test
.
ref
=
1
;
async_activate_test
.
evt
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
InitializeCriticalSection
(
&
async_activate_test
.
lock
);
async_activate_test
.
op
=
NULL
;
async_activate_test
.
main_tid
=
GetCurrentThreadId
();
async_activate_test
.
result_iface
=
NULL
;
async_activate_test
.
result_hr
=
0
;
/* try invalid device path */
strcpy
(
async_activate_test
.
msg_pfx
,
"invalid_path"
);
EnterCriticalSection
(
&
async_activate_test
.
lock
);
hr
=
pActivateAudioInterfaceAsync
(
L"winetest_bogus"
,
&
IID_IAudioClient3
,
NULL
,
&
async_activate_done
,
&
async_activate_test
.
op
);
ok
(
hr
==
S_OK
,
"ActivateAudioInterfaceAsync failed: %08x
\n
"
,
hr
);
LeaveCriticalSection
(
&
async_activate_test
.
lock
);
IActivateAudioInterfaceAsyncOperation_Release
(
async_activate_test
.
op
);
dr
=
WaitForSingleObject
(
async_activate_test
.
evt
,
1000
);
/* wait for all refs other than our own to be released */
ok
(
dr
==
WAIT_OBJECT_0
,
"Timed out waiting for async activate to complete
\n
"
);
ok
(
async_activate_test
.
ref
==
1
,
"ActivateAudioInterfaceAsync leaked a handler ref: %u
\n
"
,
async_activate_test
.
ref
);
ok
(
async_activate_test
.
result_hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
),
"mmdevice activation gave wrong result: %08x
\n
"
,
async_activate_test
.
result_hr
);
ok
(
async_activate_test
.
result_iface
==
NULL
,
"Got non-NULL iface pointer: %p
\n
"
,
async_activate_test
.
result_iface
);
/* device id from IMMDevice does not work */
if
(
g_num_mmdevs
>
0
){
strcpy
(
async_activate_test
.
msg_pfx
,
"mmdevice_id"
);
EnterCriticalSection
(
&
async_activate_test
.
lock
);
hr
=
pActivateAudioInterfaceAsync
(
g_device_path
,
&
IID_IAudioClient3
,
NULL
,
&
async_activate_done
,
&
async_activate_test
.
op
);
ok
(
hr
==
S_OK
,
"ActivateAudioInterfaceAsync failed: %08x
\n
"
,
hr
);
LeaveCriticalSection
(
&
async_activate_test
.
lock
);
IActivateAudioInterfaceAsyncOperation_Release
(
async_activate_test
.
op
);
dr
=
WaitForSingleObject
(
async_activate_test
.
evt
,
1000
);
ok
(
dr
==
WAIT_OBJECT_0
,
"Timed out waiting for async activate to complete
\n
"
);
ok
(
async_activate_test
.
ref
==
1
,
"ActivateAudioInterfaceAsync leaked a handler ref: %u
\n
"
,
async_activate_test
.
ref
);
ok
(
async_activate_test
.
result_hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
),
"mmdevice activation gave wrong result: %08x
\n
"
,
async_activate_test
.
result_hr
);
ok
(
async_activate_test
.
result_iface
==
NULL
,
"Got non-NULL iface pointer: %p
\n
"
,
async_activate_test
.
result_iface
);
}
/* try DEVINTERFACE_AUDIO_RENDER */
strcpy
(
async_activate_test
.
msg_pfx
,
"audio_render"
);
StringFromIID
(
&
DEVINTERFACE_AUDIO_RENDER
,
&
path
);
EnterCriticalSection
(
&
async_activate_test
.
lock
);
hr
=
pActivateAudioInterfaceAsync
(
path
,
&
IID_IAudioClient3
,
NULL
,
&
async_activate_done
,
&
async_activate_test
.
op
);
ok
(
hr
==
S_OK
,
"ActivateAudioInterfaceAsync failed: %08x
\n
"
,
hr
);
LeaveCriticalSection
(
&
async_activate_test
.
lock
);
IActivateAudioInterfaceAsyncOperation_Release
(
async_activate_test
.
op
);
dr
=
WaitForSingleObject
(
async_activate_test
.
evt
,
1000
);
ok
(
dr
==
WAIT_OBJECT_0
,
"Timed out waiting for async activate to complete
\n
"
);
ok
(
async_activate_test
.
ref
==
1
,
"ActivateAudioInterfaceAsync leaked a handler ref
\n
"
);
ok
(
async_activate_test
.
result_hr
==
S_OK
||
(
g_num_mmdevs
==
0
&&
async_activate_test
.
result_hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
))
||
/* no devices */
broken
(
async_activate_test
.
result_hr
==
HRESULT_FROM_WIN32
(
ERROR_FILE_NOT_FOUND
)),
/* win8 doesn't support DEVINTERFACE_AUDIO_RENDER */
"mmdevice activation gave wrong result: %08x
\n
"
,
async_activate_test
.
result_hr
);
if
(
async_activate_test
.
result_hr
==
S_OK
){
ok
(
async_activate_test
.
result_iface
!=
NULL
,
"Got NULL iface pointer on success?
\n
"
);
/* returned iface should be the IID we requested */
hr
=
IUnknown_QueryInterface
(
async_activate_test
.
result_iface
,
&
IID_IAudioClient3
,
(
void
**
)
&
ac3
);
ok
(
hr
==
S_OK
,
"Failed to query IAudioClient3: %08x
\n
"
,
hr
);
ok
(
async_activate_test
.
result_iface
==
(
IUnknown
*
)
ac3
,
"Activated interface other than IAudioClient3!
\n
"
);
IAudioClient3_Release
(
ac3
);
IUnknown_Release
(
async_activate_test
.
result_iface
);
}
CoTaskMemFree
(
path
);
CloseHandle
(
async_activate_test
.
evt
);
DeleteCriticalSection
(
&
async_activate_test
.
lock
);
}
static
HRESULT
WINAPI
notif_QueryInterface
(
IMMNotificationClient
*
iface
,
const
GUID
*
riid
,
void
**
obj
)
{
...
...
@@ -285,4 +473,6 @@ START_TEST(mmdevenum)
ok
(
hr
==
E_NOTFOUND
,
"UnregisterEndpointNotificationCallback failed: %08x
\n
"
,
hr
);
IMMDeviceEnumerator_Release
(
mme
);
test_ActivateAudioInterfaceAsync
();
}
include/mmdeviceapi.idl
View file @
2b69540e
...
...
@@ -26,6 +26,8 @@ cpp_quote("#ifndef E_UNSUPPORTED_TYPE")
cpp_quote
(
"#define E_UNSUPPORTED_TYPE HRESULT_FROM_WIN32(ERROR_UNSUPPORTED_TYPE)"
)
cpp_quote
(
"#endif"
)
cpp_quote
(
"DEFINE_GUID(DEVINTERFACE_AUDIO_RENDER, 0xe6327cad,0xdcec,0x4949,0xae,0x8a,0x99,0x1e,0x97,0x6a,0x79,0xd2);"
)
cpp_quote
(
"DEFINE_GUID(DEVINTERFACE_AUDIO_CAPTURE, 0x2eef81be,0x33fa,0x4800,0x96,0x70,0x1c,0xd4,0x74,0x97,0x2c,0x3f);"
)
cpp_quote
(
"#define DEVICE_STATE_ACTIVE 0x1"
)
cpp_quote
(
"#define DEVICE_STATE_DISABLED 0x2"
)
...
...
@@ -238,6 +240,40 @@ typedef struct _AudioExtensionParams
}
AudioExtensionParams
;
[
object
,
local
,
uuid
(
72
a22d78
-
cde4
-
431
d
-
b8cc
-
843
a71199b6d
),
nonextensible
,
pointer_default
(
unique
)
]
interface
IActivateAudioInterfaceAsyncOperation
:
IUnknown
{
HRESULT
GetActivateResult
(
[
out
]
HRESULT
*
result
,
[
out
]
IUnknown
**
iface
)
;
}
[
object
,
local
,
uuid
(
41
d949ab
-
9862
-
444
a
-
80
f6
-
c261334da5eb
),
nonextensible
,
pointer_default
(
unique
)
]
interface
IActivateAudioInterfaceCompletionHandler
:
IUnknown
{
HRESULT
ActivateCompleted
(
[
in
]
IActivateAudioInterfaceAsyncOperation
*
op
)
;
}
cpp_quote
(
"HRESULT WINAPI ActivateAudioInterfaceAsync("
)
cpp_quote
(
" const WCHAR *path, REFIID riid, PROPVARIANT *params,"
)
cpp_quote
(
" IActivateAudioInterfaceCompletionHandler *done_handler,"
)
cpp_quote
(
" IActivateAudioInterfaceAsyncOperation **op);"
)
[
uuid
(
2
fdaafa3
-
7523
-
4
f66
-
9957
-
9
d5e7fe698f6
),
version
(
1.0
)
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment