/* DirectSound * * Copyright 1998 Marcus Meissner * Copyright 1998 Rob Riggs * Copyright 2000-2002 TransGaming Technologies, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS #include #include "windef.h" #include "winbase.h" #include "winuser.h" #include "mmsystem.h" #include "winternl.h" #include "winnls.h" #include "vfwmsgs.h" #include "mmddk.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" #include "dsound_private.h" #include "dsconf.h" #ifdef NONAMELESSSTRUCT # define S(x) (x).s #else # define S(x) (x) #endif WINE_DEFAULT_DEBUG_CHANNEL(dsound); /******************************************************************************* * IKsPrivatePropertySet */ /* IUnknown methods */ static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface( LPKSPROPERTYSET iface, REFIID riid, LPVOID *ppobj ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IKsPropertySet)) { *ppobj = iface; IUnknown_AddRef(iface); return S_OK; } *ppobj = NULL; return E_NOINTERFACE; } static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); } return ref; } static HRESULT DSPROPERTY_WaveDeviceMappingW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { HRESULT hr = DSERR_INVALIDPARAM; PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd; TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); ppd = pPropData; if (!ppd) { WARN("invalid parameter: pPropData\n"); return DSERR_INVALIDPARAM; } if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) { ULONG wod; unsigned int wodn; TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n"); wodn = waveOutGetNumDevs(); for (wod = 0; wod < wodn; wod++) { WAVEOUTCAPSW capsW; MMRESULT res; res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW)); if (res == MMSYSERR_NOERROR) { if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) { ppd->DeviceId = DSOUND_renderer_guids[wod]; hr = DS_OK; TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId), debugstr_w(ppd->DeviceName)); break; } } } } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) { ULONG wid; unsigned int widn; TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n"); widn = waveInGetNumDevs(); for (wid = 0; wid < widn; wid++) { WAVEINCAPSW capsW; MMRESULT res; res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW)); if (res == MMSYSERR_NOERROR) { if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) { ppd->DeviceId = DSOUND_capture_guids[wid]; hr = DS_OK; TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId), debugstr_w(ppd->DeviceName)); break; } } } } if (pcbReturned) *pcbReturned = cbPropData; return hr; } static HRESULT DSPROPERTY_WaveDeviceMappingA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA *ppd = pPropData; DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA data; DWORD len; HRESULT hr; TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); if (!ppd || !ppd->DeviceName) { WARN("invalid parameter: ppd=%p\n", ppd); return DSERR_INVALIDPARAM; } data.DataFlow = ppd->DataFlow; len = MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, NULL, 0); data.DeviceName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!data.DeviceName) return E_OUTOFMEMORY; MultiByteToWideChar(CP_ACP, 0, ppd->DeviceName, -1, data.DeviceName, len); hr = DSPROPERTY_WaveDeviceMappingW(&data, cbPropData, pcbReturned); HeapFree(GetProcessHeap(), 0, data.DeviceName); ppd->DeviceId = data.DeviceId; if (pcbReturned) *pcbReturned = cbPropData; return hr; } static HRESULT DSPROPERTY_DescriptionW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData; HRESULT err; GUID dev_guid; ULONG wod, wid, wodn, widn; DSDRIVERDESC desc; TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId)); if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) { /* default device of type specified by ppd->DataFlow */ if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) { TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n"); ppd->DeviceId = DSDEVID_DefaultCapture; } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) { TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n"); ppd->DeviceId = DSDEVID_DefaultPlayback; } else { WARN("DataFlow=Unknown(%d)\n", ppd->DataFlow); return E_PROP_ID_UNSUPPORTED; } } GetDeviceID(&ppd->DeviceId, &dev_guid); wodn = waveOutGetNumDevs(); widn = waveInGetNumDevs(); wid = wod = dev_guid.Data4[7]; if (!memcmp(&dev_guid, &DSOUND_renderer_guids[0], sizeof(GUID)-1) && wod < wodn) { ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; ppd->WaveDeviceId = wod; } else if (!memcmp(&dev_guid, &DSOUND_capture_guids[0], sizeof(GUID)-1) && wid < widn) { ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; ppd->WaveDeviceId = wid; } else { WARN("Device not found\n"); return E_PROP_ID_UNSUPPORTED; } if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0); else err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0); if (err != MMSYSERR_NOERROR) { WARN("waveMessage(DRV_QUERYDSOUNDDESC) failed!\n"); return E_PROP_ID_UNSUPPORTED; } else { /* FIXME: Still a memory leak.. */ int desclen, modlen; static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 }; modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 ); desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 ); ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR)); ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR)); ppd->Interface = wInterface; if (!ppd->Description || !ppd->Module) { WARN("Out of memory\n"); HeapFree(GetProcessHeap(), 0, ppd->Description); HeapFree(GetProcessHeap(), 0, ppd->Module); ppd->Description = ppd->Module = NULL; return E_OUTOFMEMORY; } MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen ); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen ); } ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; if (pcbReturned) { *pcbReturned = sizeof(*ppd); TRACE("*pcbReturned=%d\n", *pcbReturned); } return S_OK; } static HRESULT DSPROPERTY_EnumerateW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData; DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data; BOOL ret; int widn, wodn, i; TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); if (pcbReturned) *pcbReturned = 0; if (!ppd || !ppd->Callback) { WARN("Invalid ppd %p\n", ppd); return E_PROP_ID_UNSUPPORTED; } wodn = waveOutGetNumDevs(); widn = waveInGetNumDevs(); data.DeviceId = DSOUND_renderer_guids[0]; for (i = 0; i < wodn; ++i) { HRESULT hr; data.DeviceId.Data4[7] = i; hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL); if (FAILED(hr)) { ERR("DescriptionW failed!\n"); return S_OK; } ret = ppd->Callback(&data, ppd->Context); HeapFree(GetProcessHeap(), 0, data.Module); HeapFree(GetProcessHeap(), 0, data.Description); if (!ret) return S_OK; } data.DeviceId = DSOUND_capture_guids[0]; for (i = 0; i < widn; ++i) { HRESULT hr; data.DeviceId.Data4[7] = i; hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL); if (FAILED(hr)) { ERR("DescriptionW failed!\n"); return S_OK; } ret = ppd->Callback(&data, ppd->Context); HeapFree(GetProcessHeap(), 0, data.Module); HeapFree(GetProcessHeap(), 0, data.Description); if (!ret) return S_OK; } return S_OK; } static BOOL DSPROPERTY_descWtoA(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW, DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *dataA) { DWORD modlen, desclen; static char Interface[] = "Interface"; modlen = WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, NULL, 0, NULL, NULL); desclen = WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, NULL, 0, NULL, NULL); dataA->Type = dataW->Type; dataA->DataFlow = dataW->DataFlow; dataA->DeviceId = dataW->DeviceId; dataA->WaveDeviceId = dataW->WaveDeviceId; dataA->Interface = Interface; dataA->Module = HeapAlloc(GetProcessHeap(), 0, modlen); dataA->Description = HeapAlloc(GetProcessHeap(), 0, desclen); if (!dataA->Module || !dataA->Description) { HeapFree(GetProcessHeap(), 0, dataA->Module); HeapFree(GetProcessHeap(), 0, dataA->Description); dataA->Module = dataA->Description = NULL; return FALSE; } WideCharToMultiByte(CP_ACP, 0, dataW->Module, -1, dataA->Module, modlen, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, dataW->Description, -1, dataA->Description, desclen, NULL, NULL); return TRUE; } static void DSPROPERTY_descWto1(const DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *dataW, DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *data1) { data1->DeviceId = dataW->DeviceId; lstrcpynW(data1->ModuleW, dataW->Module, sizeof(data1->ModuleW)/sizeof(*data1->ModuleW)); lstrcpynW(data1->DescriptionW, dataW->Description, sizeof(data1->DescriptionW)/sizeof(*data1->DescriptionW)); WideCharToMultiByte(CP_ACP, 0, data1->DescriptionW, -1, data1->DescriptionA, sizeof(data1->DescriptionA)-1, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, data1->ModuleW, -1, data1->ModuleA, sizeof(data1->ModuleA)-1, NULL, NULL); data1->DescriptionA[sizeof(data1->DescriptionA)-1] = 0; data1->ModuleA[sizeof(data1->ModuleA)-1] = 0; data1->Type = dataW->Type; data1->DataFlow = dataW->DataFlow; data1->WaveDeviceId = data1->Devnode = dataW->WaveDeviceId; } static BOOL CALLBACK DSPROPERTY_enumWtoA(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data) { DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA descA; DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = data; BOOL ret; ret = DSPROPERTY_descWtoA(descW, &descA); if (!ret) return FALSE; ret = ppd->Callback(&descA, ppd->Context); HeapFree(GetProcessHeap(), 0, descA.Module); HeapFree(GetProcessHeap(), 0, descA.Description); return ret; } static HRESULT DSPROPERTY_EnumerateA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned) { DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA *ppd = pPropData; DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data; if (!ppd || !ppd->Callback) { WARN("Invalid ppd %p\n", ppd); return E_PROP_ID_UNSUPPORTED; } data.Callback = DSPROPERTY_enumWtoA; data.Context = ppd; return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned); } static BOOL CALLBACK DSPROPERTY_enumWto1(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA *descW, void *data) { DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA desc1; DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = data; BOOL ret; DSPROPERTY_descWto1(descW, &desc1); ret = ppd->Callback(&desc1, ppd->Context); return ret; } static HRESULT DSPROPERTY_Enumerate1( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned) { DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA *ppd = pPropData; DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA data; if (!ppd || !ppd->Callback) { WARN("Invalid ppd %p\n", ppd); return E_PROP_ID_UNSUPPORTED; } data.Callback = DSPROPERTY_enumWto1; data.Context = ppd; return DSPROPERTY_EnumerateW(&data, cbPropData, pcbReturned); } static HRESULT DSPROPERTY_DescriptionA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned) { DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data; DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA *ppd = pPropData; HRESULT hr; if (pcbReturned) *pcbReturned = sizeof(*ppd); if (!pPropData) return S_OK; data.DeviceId = ppd->DeviceId; data.DataFlow = ppd->DataFlow; hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL); if (FAILED(hr)) return hr; if (!DSPROPERTY_descWtoA(&data, ppd)) hr = E_OUTOFMEMORY; HeapFree(GetProcessHeap(), 0, data.Module); HeapFree(GetProcessHeap(), 0, data.Interface); return hr; } static HRESULT DSPROPERTY_Description1( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned) { DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data; DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA *ppd = pPropData; HRESULT hr; if (pcbReturned) *pcbReturned = sizeof(*ppd); if (!pPropData) return S_OK; data.DeviceId = ppd->DeviceId; data.DataFlow = ppd->DataFlow; hr = DSPROPERTY_DescriptionW(&data, sizeof(data), NULL); if (FAILED(hr)) return hr; DSPROPERTY_descWto1(&data, ppd); HeapFree(GetProcessHeap(), 0, data.Module); HeapFree(GetProcessHeap(), 0, data.Interface); return hr; } static HRESULT WINAPI IKsPrivatePropertySetImpl_Get( LPKSPROPERTYSET iface, REFGUID guidPropSet, ULONG dwPropID, LPVOID pInstanceData, ULONG cbInstanceData, LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned); if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { switch (dwPropID) { case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A: return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1: return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1: return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W: return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A: return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W: return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A: return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned); case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W: return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned); default: FIXME("unsupported ID: %d\n",dwPropID); break; } } else { FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); } if (pcbReturned) { *pcbReturned = 0; FIXME("*pcbReturned=%d\n", *pcbReturned); } return E_PROP_ID_UNSUPPORTED; } static HRESULT WINAPI IKsPrivatePropertySetImpl_Set( LPKSPROPERTYSET iface, REFGUID guidPropSet, ULONG dwPropID, LPVOID pInstanceData, ULONG cbInstanceData, LPVOID pPropData, ULONG cbPropData ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData); return E_PROP_ID_UNSUPPORTED; } static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport( LPKSPROPERTYSET iface, REFGUID guidPropSet, ULONG dwPropID, PULONG pTypeSupport ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport); if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { switch (dwPropID) { case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W: *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; default: FIXME("unsupported ID: %d\n",dwPropID); break; } } else { FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); } return E_PROP_ID_UNSUPPORTED; } static const IKsPropertySetVtbl ikspvt = { IKsPrivatePropertySetImpl_QueryInterface, IKsPrivatePropertySetImpl_AddRef, IKsPrivatePropertySetImpl_Release, IKsPrivatePropertySetImpl_Get, IKsPrivatePropertySetImpl_Set, IKsPrivatePropertySetImpl_QuerySupport }; HRESULT IKsPrivatePropertySetImpl_Create( REFIID riid, IKsPrivatePropertySetImpl **piks) { IKsPrivatePropertySetImpl *iks; TRACE("(%s, %p)\n", debugstr_guid(riid), piks); if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IKsPropertySet)) { *piks = 0; return E_NOINTERFACE; } iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks)); iks->ref = 1; iks->lpVtbl = &ikspvt; *piks = iks; return S_OK; }