xref: /reactos/dll/directx/wine/dxdiagn/container.c (revision 3435c3b5)
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