1 /* 2 * Implementation of IEnumPins Interface 3 * 4 * Copyright 2003 Robert Shearman 5 * Copyright 2010 Aric Stewart, CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 24 #include "dshow.h" 25 #include "wine/strmbase.h" 26 #include "wine/debug.h" 27 28 WINE_DEFAULT_DEBUG_CHANNEL(strmbase); 29 30 typedef struct IEnumPinsImpl 31 { 32 IEnumPins IEnumPins_iface; 33 LONG refCount; 34 ULONG uIndex; 35 BaseFilter *base; 36 BaseFilter_GetPin receive_pin; 37 BaseFilter_GetPinCount receive_pincount; 38 BaseFilter_GetPinVersion receive_version; 39 DWORD Version; 40 } IEnumPinsImpl; 41 42 static inline IEnumPinsImpl *impl_from_IEnumPins(IEnumPins *iface) 43 { 44 return CONTAINING_RECORD(iface, IEnumPinsImpl, IEnumPins_iface); 45 } 46 47 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl; 48 49 HRESULT WINAPI EnumPins_Construct(BaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum) 50 { 51 IEnumPinsImpl * pEnumPins; 52 53 if (!ppEnum) 54 return E_POINTER; 55 56 pEnumPins = CoTaskMemAlloc(sizeof(IEnumPinsImpl)); 57 if (!pEnumPins) 58 { 59 *ppEnum = NULL; 60 return E_OUTOFMEMORY; 61 } 62 pEnumPins->IEnumPins_iface.lpVtbl = &IEnumPinsImpl_Vtbl; 63 pEnumPins->refCount = 1; 64 pEnumPins->uIndex = 0; 65 pEnumPins->receive_pin = receive_pin; 66 pEnumPins->receive_pincount = receive_pincount; 67 pEnumPins->receive_version = receive_version; 68 pEnumPins->base = base; 69 IBaseFilter_AddRef(&base->IBaseFilter_iface); 70 *ppEnum = &pEnumPins->IEnumPins_iface; 71 pEnumPins->Version = receive_version(base); 72 73 TRACE("Created new enumerator (%p)\n", *ppEnum); 74 return S_OK; 75 } 76 77 static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID riid, LPVOID * ppv) 78 { 79 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); 80 81 *ppv = NULL; 82 83 if (IsEqualIID(riid, &IID_IUnknown)) 84 *ppv = iface; 85 else if (IsEqualIID(riid, &IID_IEnumPins)) 86 *ppv = iface; 87 88 if (*ppv) 89 { 90 IUnknown_AddRef((IUnknown *)(*ppv)); 91 return S_OK; 92 } 93 94 FIXME("No interface for %s!\n", debugstr_guid(riid)); 95 96 return E_NOINTERFACE; 97 } 98 99 static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface) 100 { 101 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 102 ULONG ref = InterlockedIncrement(&This->refCount); 103 104 TRACE("(%p)->(): new ref = %u\n", iface, ref); 105 106 return ref; 107 } 108 109 static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface) 110 { 111 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 112 ULONG ref = InterlockedDecrement(&This->refCount); 113 114 TRACE("(%p)->(): new ref = %u\n", iface, ref); 115 116 if (!ref) 117 { 118 IBaseFilter_Release(&This->base->IBaseFilter_iface); 119 CoTaskMemFree(This); 120 } 121 122 return ref; 123 } 124 125 static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched) 126 { 127 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 128 ULONG i = 0; 129 130 TRACE("(%p)->(%u, %p, %p)\n", iface, cPins, ppPins, pcFetched); 131 132 if (!ppPins) 133 return E_POINTER; 134 135 if (cPins > 1 && !pcFetched) 136 return E_INVALIDARG; 137 138 if (pcFetched) 139 *pcFetched = 0; 140 141 if (This->Version != This->receive_version(This->base)) 142 return VFW_E_ENUM_OUT_OF_SYNC; 143 144 while (i < cPins) 145 { 146 IPin *pin; 147 pin = This->receive_pin(This->base, This->uIndex + i); 148 149 if (!pin) 150 break; 151 else 152 ppPins[i] = pin; 153 ++i; 154 } 155 156 if (pcFetched) 157 *pcFetched = i; 158 This->uIndex += i; 159 160 if (i < cPins) 161 return S_FALSE; 162 return S_OK; 163 } 164 165 static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins) 166 { 167 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 168 169 TRACE("(%p)->(%u)\n", iface, cPins); 170 171 if (This->Version != This->receive_version(This->base)) 172 return VFW_E_ENUM_OUT_OF_SYNC; 173 174 if (This->receive_pincount(This->base) >= This->uIndex + cPins) 175 return S_FALSE; 176 177 This->uIndex += cPins; 178 return S_OK; 179 } 180 181 static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface) 182 { 183 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 184 185 TRACE("(%p)->()\n", iface); 186 187 This->Version = This->receive_version(This->base); 188 189 This->uIndex = 0; 190 return S_OK; 191 } 192 193 static HRESULT WINAPI IEnumPinsImpl_Clone(IEnumPins * iface, IEnumPins ** ppEnum) 194 { 195 HRESULT hr; 196 IEnumPinsImpl *This = impl_from_IEnumPins(iface); 197 198 TRACE("(%p)->(%p)\n", iface, ppEnum); 199 200 hr = EnumPins_Construct(This->base, This->receive_pin, This->receive_pincount, This->receive_version, ppEnum); 201 if (FAILED(hr)) 202 return hr; 203 return IEnumPins_Skip(*ppEnum, This->uIndex); 204 } 205 206 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl = 207 { 208 IEnumPinsImpl_QueryInterface, 209 IEnumPinsImpl_AddRef, 210 IEnumPinsImpl_Release, 211 IEnumPinsImpl_Next, 212 IEnumPinsImpl_Skip, 213 IEnumPinsImpl_Reset, 214 IEnumPinsImpl_Clone 215 }; 216