1 /* 2 * IDxDiagContainer Implementation 3 * 4 * Copyright 2004 Raphael Junqueira 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 */ 21 22 23 #define COBJMACROS 24 #include "dxdiag_private.h" 25 #include "wine/debug.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(dxdiag); 28 29 static inline IDxDiagContainerImpl *impl_from_IDxDiagContainer(IDxDiagContainer *iface) 30 { 31 return CONTAINING_RECORD(iface, IDxDiagContainerImpl, IDxDiagContainer_iface); 32 } 33 34 /* IDxDiagContainer IUnknown parts follow: */ 35 static HRESULT WINAPI IDxDiagContainerImpl_QueryInterface(IDxDiagContainer *iface, REFIID riid, 36 void **ppobj) 37 { 38 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 39 40 if (!ppobj) return E_INVALIDARG; 41 42 if (IsEqualGUID(riid, &IID_IUnknown) 43 || IsEqualGUID(riid, &IID_IDxDiagContainer)) { 44 IUnknown_AddRef(iface); 45 *ppobj = This; 46 return S_OK; 47 } 48 49 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj); 50 *ppobj = NULL; 51 return E_NOINTERFACE; 52 } 53 54 static ULONG WINAPI IDxDiagContainerImpl_AddRef(IDxDiagContainer *iface) 55 { 56 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 57 ULONG refCount = InterlockedIncrement(&This->ref); 58 59 TRACE("(%p)->(ref before=%u)\n", This, refCount - 1); 60 61 DXDIAGN_LockModule(); 62 63 return refCount; 64 } 65 66 static ULONG WINAPI IDxDiagContainerImpl_Release(IDxDiagContainer *iface) 67 { 68 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 69 ULONG refCount = InterlockedDecrement(&This->ref); 70 71 TRACE("(%p)->(ref before=%u)\n", This, refCount + 1); 72 73 if (!refCount) { 74 IDxDiagProvider_Release(This->pProv); 75 HeapFree(GetProcessHeap(), 0, This); 76 } 77 78 DXDIAGN_UnlockModule(); 79 80 return refCount; 81 } 82 83 /* IDxDiagContainer Interface follow: */ 84 static HRESULT WINAPI IDxDiagContainerImpl_GetNumberOfChildContainers(IDxDiagContainer *iface, 85 DWORD *pdwCount) 86 { 87 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 88 89 TRACE("(%p)\n", iface); 90 if (NULL == pdwCount) { 91 return E_INVALIDARG; 92 } 93 *pdwCount = This->cont->nSubContainers; 94 return S_OK; 95 } 96 97 static HRESULT WINAPI IDxDiagContainerImpl_EnumChildContainerNames(IDxDiagContainer *iface, 98 DWORD dwIndex, LPWSTR pwszContainer, DWORD cchContainer) 99 { 100 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 101 IDxDiagContainerImpl_Container *p; 102 DWORD i = 0; 103 104 TRACE("(%p, %u, %p, %u)\n", iface, dwIndex, pwszContainer, cchContainer); 105 106 if (NULL == pwszContainer || 0 == cchContainer) { 107 return E_INVALIDARG; 108 } 109 110 LIST_FOR_EACH_ENTRY(p, &This->cont->subContainers, IDxDiagContainerImpl_Container, entry) 111 { 112 if (dwIndex == i) { 113 TRACE("Found container name %s, copying string\n", debugstr_w(p->contName)); 114 lstrcpynW(pwszContainer, p->contName, cchContainer); 115 return (cchContainer <= lstrlenW(p->contName)) ? 116 DXDIAG_E_INSUFFICIENT_BUFFER : S_OK; 117 } 118 ++i; 119 } 120 121 TRACE("Failed to find container name at specified index\n"); 122 *pwszContainer = '\0'; 123 return E_INVALIDARG; 124 } 125 126 static HRESULT IDxDiagContainerImpl_GetChildContainerInternal(IDxDiagContainerImpl_Container *cont, LPCWSTR pwszContainer, IDxDiagContainerImpl_Container **subcont) { 127 IDxDiagContainerImpl_Container *p; 128 129 LIST_FOR_EACH_ENTRY(p, &cont->subContainers, IDxDiagContainerImpl_Container, entry) 130 { 131 if (0 == lstrcmpW(p->contName, pwszContainer)) { 132 *subcont = p; 133 return S_OK; 134 } 135 } 136 137 return E_INVALIDARG; 138 } 139 140 static HRESULT WINAPI IDxDiagContainerImpl_GetChildContainer(IDxDiagContainer *iface, 141 LPCWSTR pwszContainer, IDxDiagContainer **ppInstance) 142 { 143 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 144 IDxDiagContainerImpl_Container *pContainer = This->cont; 145 LPWSTR tmp, orig_tmp; 146 INT tmp_len; 147 WCHAR* cur; 148 HRESULT hr = E_INVALIDARG; 149 150 TRACE("(%p, %s, %p)\n", iface, debugstr_w(pwszContainer), ppInstance); 151 152 if (NULL == ppInstance || NULL == pwszContainer) { 153 return E_INVALIDARG; 154 } 155 156 *ppInstance = NULL; 157 158 tmp_len = lstrlenW(pwszContainer) + 1; 159 orig_tmp = tmp = HeapAlloc(GetProcessHeap(), 0, tmp_len * sizeof(WCHAR)); 160 if (NULL == tmp) return E_FAIL; 161 lstrcpynW(tmp, pwszContainer, tmp_len); 162 163 cur = wcschr(tmp, '.'); 164 while (NULL != cur) { 165 *cur = '\0'; /* cut tmp string to '.' */ 166 if (!*(cur + 1)) break; /* Account for a lone terminating period, as in "cont1.cont2.". */ 167 TRACE("Trying to get parent container %s\n", debugstr_w(tmp)); 168 hr = IDxDiagContainerImpl_GetChildContainerInternal(pContainer, tmp, &pContainer); 169 if (FAILED(hr)) 170 goto out; 171 cur++; /* go after '.' (just replaced by \0) */ 172 tmp = cur; 173 cur = wcschr(tmp, '.'); 174 } 175 176 TRACE("Trying to get container %s\n", debugstr_w(tmp)); 177 hr = IDxDiagContainerImpl_GetChildContainerInternal(pContainer, tmp, &pContainer); 178 if (SUCCEEDED(hr)) { 179 hr = DXDiag_CreateDXDiagContainer(&IID_IDxDiagContainer, pContainer, This->pProv, (void **)ppInstance); 180 if (SUCCEEDED(hr)) 181 TRACE("Succeeded in getting the container instance\n"); 182 } 183 184 out: 185 HeapFree(GetProcessHeap(), 0, orig_tmp); 186 return hr; 187 } 188 189 static HRESULT WINAPI IDxDiagContainerImpl_GetNumberOfProps(IDxDiagContainer *iface, 190 DWORD *pdwCount) 191 { 192 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 193 194 TRACE("(%p)\n", iface); 195 if (NULL == pdwCount) { 196 return E_INVALIDARG; 197 } 198 *pdwCount = This->cont->nProperties; 199 return S_OK; 200 } 201 202 static HRESULT WINAPI IDxDiagContainerImpl_EnumPropNames(IDxDiagContainer *iface, DWORD dwIndex, 203 LPWSTR pwszPropName, DWORD cchPropName) 204 { 205 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 206 IDxDiagContainerImpl_Property *p; 207 DWORD i = 0; 208 209 TRACE("(%p, %u, %p, %u)\n", iface, dwIndex, pwszPropName, cchPropName); 210 211 if (NULL == pwszPropName || 0 == cchPropName) { 212 return E_INVALIDARG; 213 } 214 215 LIST_FOR_EACH_ENTRY(p, &This->cont->properties, IDxDiagContainerImpl_Property, entry) 216 { 217 if (dwIndex == i) { 218 TRACE("Found property name %s, copying string\n", debugstr_w(p->propName)); 219 lstrcpynW(pwszPropName, p->propName, cchPropName); 220 return (cchPropName <= lstrlenW(p->propName)) ? 221 DXDIAG_E_INSUFFICIENT_BUFFER : S_OK; 222 } 223 ++i; 224 } 225 226 TRACE("Failed to find property name at specified index\n"); 227 return E_INVALIDARG; 228 } 229 230 static HRESULT WINAPI IDxDiagContainerImpl_GetProp(IDxDiagContainer *iface, LPCWSTR pwszPropName, 231 VARIANT *pvarProp) 232 { 233 IDxDiagContainerImpl *This = impl_from_IDxDiagContainer(iface); 234 IDxDiagContainerImpl_Property *p; 235 236 TRACE("(%p, %s, %p)\n", iface, debugstr_w(pwszPropName), pvarProp); 237 238 if (NULL == pvarProp || NULL == pwszPropName) { 239 return E_INVALIDARG; 240 } 241 242 LIST_FOR_EACH_ENTRY(p, &This->cont->properties, IDxDiagContainerImpl_Property, entry) 243 { 244 if (0 == lstrcmpW(p->propName, pwszPropName)) { 245 VariantInit(pvarProp); 246 return VariantCopy(pvarProp, &p->vProp); 247 } 248 } 249 250 return E_INVALIDARG; 251 } 252 253 static const IDxDiagContainerVtbl DxDiagContainer_Vtbl = 254 { 255 IDxDiagContainerImpl_QueryInterface, 256 IDxDiagContainerImpl_AddRef, 257 IDxDiagContainerImpl_Release, 258 IDxDiagContainerImpl_GetNumberOfChildContainers, 259 IDxDiagContainerImpl_EnumChildContainerNames, 260 IDxDiagContainerImpl_GetChildContainer, 261 IDxDiagContainerImpl_GetNumberOfProps, 262 IDxDiagContainerImpl_EnumPropNames, 263 IDxDiagContainerImpl_GetProp 264 }; 265 266 267 HRESULT DXDiag_CreateDXDiagContainer(REFIID riid, IDxDiagContainerImpl_Container *cont, IDxDiagProvider *pProv, LPVOID *ppobj) { 268 IDxDiagContainerImpl* container; 269 270 TRACE("(%s, %p)\n", debugstr_guid(riid), ppobj); 271 272 container = HeapAlloc(GetProcessHeap(), 0, sizeof(IDxDiagContainerImpl)); 273 if (NULL == container) { 274 *ppobj = NULL; 275 return E_OUTOFMEMORY; 276 } 277 container->IDxDiagContainer_iface.lpVtbl = &DxDiagContainer_Vtbl; 278 container->ref = 0; /* will be inited with QueryInterface */ 279 container->cont = cont; 280 container->pProv = pProv; 281 IDxDiagProvider_AddRef(pProv); 282 return IDxDiagContainerImpl_QueryInterface(&container->IDxDiagContainer_iface, riid, ppobj); 283 } 284