1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxCollectionApi.cpp
8 
9 Abstract:
10 
11     This module implements the "C" interface to the collection object.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 --*/
24 
25 #include "fxsupportpch.hpp"
26 
27 extern "C" {
28 // #include "FxCollectionApi.tmh"
29 }
30 
31 //
32 // Extern the entire file
33 //
34 extern "C" {
35 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)36 __drv_maxIRQL(DISPATCH_LEVEL)
37 NTSTATUS
38 STDCALL
39 WDFEXPORT(WdfCollectionCreate)(
40     __in
41     PWDF_DRIVER_GLOBALS DriverGlobals,
42     __in_opt
43     PWDF_OBJECT_ATTRIBUTES CollectionAttributes,
44     __out
45     WDFCOLLECTION *Collection
46     )
47 {
48     DDI_ENTRY();
49 
50     PFX_DRIVER_GLOBALS pFxDriverGlobals;
51     NTSTATUS status;
52     FxCollection *pCollection;
53     WDFCOLLECTION hCol;
54 
55     pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
56 
57     //
58     // Get the parent's globals if it is present
59     //
60     if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(
61                         pFxDriverGlobals, CollectionAttributes))) {
62         FxObject* pParent;
63 
64         FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
65                                        CollectionAttributes->ParentObject,
66                                        FX_TYPE_OBJECT,
67                                        (PVOID*)&pParent,
68                                        &pFxDriverGlobals);
69     }
70 
71     FxPointerNotNull(pFxDriverGlobals, Collection);
72 
73     *Collection = NULL;
74 
75     status = FxValidateObjectAttributes(pFxDriverGlobals, CollectionAttributes);
76     if (!NT_SUCCESS(status)) {
77         return status;
78     }
79 
80     pCollection = new (pFxDriverGlobals, CollectionAttributes)
81         FxCollection(pFxDriverGlobals);
82 
83     if (pCollection != NULL) {
84         status = pCollection->Commit(CollectionAttributes, (WDFOBJECT*)&hCol);
85 
86         if (NT_SUCCESS(status)) {
87             *Collection = hCol;
88         }
89         else {
90             DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
91                                 "Could not create collection object: %!STATUS!",
92                                 status);
93 
94             pCollection->DeleteFromFailedCreate();
95         }
96     }
97     else {
98         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
99                             "Could not create collection object: "
100                             "STATUS_INSUFFICIENT_RESOURCES" );
101         status = STATUS_INSUFFICIENT_RESOURCES;
102     }
103 
104     return status;
105 }
106 
__drv_maxIRQL(DISPATCH_LEVEL)107 __drv_maxIRQL(DISPATCH_LEVEL)
108 ULONG
109 STDCALL
110 WDFEXPORT(WdfCollectionGetCount)(
111     __in
112     PWDF_DRIVER_GLOBALS DriverGlobals,
113     __in
114     WDFCOLLECTION Collection
115     )
116 {
117     DDI_ENTRY();
118 
119     FxCollection *pCollection;
120     KIRQL irql;
121     ULONG count;
122 
123     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
124                          Collection,
125                          FX_TYPE_COLLECTION,
126                          (PVOID *)&pCollection);
127 
128     pCollection->Lock(&irql);
129     count = pCollection->Count();
130     pCollection->Unlock(irql);
131 
132     return count;
133 }
134 
135 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)136 __drv_maxIRQL(DISPATCH_LEVEL)
137 NTSTATUS
138 STDCALL
139 WDFEXPORT(WdfCollectionAdd)(
140     __in
141     PWDF_DRIVER_GLOBALS DriverGlobals,
142     __in
143     WDFCOLLECTION Collection,
144     __in
145     WDFOBJECT Object
146     )
147 {
148     DDI_ENTRY();
149 
150     PFX_DRIVER_GLOBALS pFxDriverGlobals;
151     FxCollection *pCollection;
152     FxObject *pObject;
153     NTSTATUS status;
154     KIRQL irql;
155 
156     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
157                                    Collection,
158                                    FX_TYPE_COLLECTION,
159                                    (PVOID*) &pCollection,
160                                    &pFxDriverGlobals);
161 
162     FxObjectHandleGetPtr(pFxDriverGlobals,
163                          Object,
164                          FX_TYPE_OBJECT,
165                          (PVOID*) &pObject);
166 
167     pCollection->Lock(&irql);
168     status = pCollection->Add(pObject) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
169     pCollection->Unlock(irql);
170 
171     return status;
172 }
173 
__drv_maxIRQL(DISPATCH_LEVEL)174 __drv_maxIRQL(DISPATCH_LEVEL)
175 VOID
176 STDCALL
177 WDFEXPORT(WdfCollectionRemoveItem)(
178     __in
179     PWDF_DRIVER_GLOBALS DriverGlobals,
180     __in
181     WDFCOLLECTION Collection,
182     __in
183     ULONG Index
184     )
185 {
186     DDI_ENTRY();
187 
188     PFX_DRIVER_GLOBALS pFxDriverGlobals;
189     FxCollection* pCollection;
190     FxCollectionEntry* pEntry;
191     FxObject* pObject;
192     NTSTATUS status;
193     KIRQL irql;
194 
195     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
196                                    Collection,
197                                    FX_TYPE_COLLECTION,
198                                    (PVOID*) &pCollection,
199                                    &pFxDriverGlobals);
200 
201     pCollection->Lock(&irql);
202 
203     pEntry = pCollection->FindEntry(Index);
204 
205     if (pEntry != NULL) {
206         pObject = pEntry->m_Object;
207         pCollection->CleanupEntry(pEntry);
208         status = STATUS_SUCCESS;
209     }
210     else {
211         pObject = NULL;
212         status = STATUS_NOT_FOUND;
213     }
214 
215     pCollection->Unlock(irql);
216 
217     if (pObject != NULL) {
218         pCollection->CleanupEntryObject(pObject);
219     }
220 
221     if (!NT_SUCCESS(status)) {
222         DoTraceLevelMessage(
223             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
224             "Index %d is not valid in WDFCOLLECTION %p (count is %d), %!STATUS!",
225             Index, Collection, pCollection->Count(), status);
226         FxVerifierDbgBreakPoint(pFxDriverGlobals);
227     }
228 }
229 
__drv_maxIRQL(DISPATCH_LEVEL)230 __drv_maxIRQL(DISPATCH_LEVEL)
231 VOID
232 STDCALL
233 WDFEXPORT(WdfCollectionRemove)(
234     __in
235     PWDF_DRIVER_GLOBALS DriverGlobals,
236     __in
237     WDFCOLLECTION Collection,
238     __in
239     WDFOBJECT Item
240     )
241 {
242     DDI_ENTRY();
243 
244     PFX_DRIVER_GLOBALS pFxDriverGlobals;
245     FxCollection *pCollection;
246     FxCollectionEntry *pEntry;
247     FxObject* pObject;
248     NTSTATUS status;
249     KIRQL irql;
250 
251     FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
252                                    Collection,
253                                    FX_TYPE_COLLECTION,
254                                    (PVOID*) &pCollection,
255                                    &pFxDriverGlobals);
256 
257     FxObjectHandleGetPtr(pFxDriverGlobals,
258                          Item,
259                          FX_TYPE_OBJECT,
260                          (PVOID*) &pObject);
261 
262     pCollection->Lock(&irql);
263 
264     pEntry = pCollection->FindEntryByObject(pObject);
265 
266     if (pEntry != NULL) {
267         pCollection->CleanupEntry(pEntry);
268         status = STATUS_SUCCESS;
269     }
270     else {
271         pObject = NULL;
272         status = STATUS_NOT_FOUND;
273     }
274 
275     pCollection->Unlock(irql);
276 
277     if (pObject != NULL) {
278         pCollection->CleanupEntryObject(pObject);
279     }
280 
281     if (!NT_SUCCESS(status)) {
282         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
283                             "WDFOBJECT %p not in WDFCOLLECTION %p, %!STATUS!",
284                             Item, Collection, status);
285         FxVerifierDbgBreakPoint(pFxDriverGlobals);
286     }
287 }
288 
__drv_maxIRQL(DISPATCH_LEVEL)289 __drv_maxIRQL(DISPATCH_LEVEL)
290 WDFOBJECT
291 STDCALL
292 WDFEXPORT(WdfCollectionGetItem)(
293     __in
294     PWDF_DRIVER_GLOBALS DriverGlobals,
295     __in
296     WDFCOLLECTION Collection,
297     __in
298     ULONG Index
299     )
300 {
301     DDI_ENTRY();
302 
303     FxCollection *pCollection;
304     FxObject *pObject;
305     KIRQL irql;
306 
307     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
308                          Collection,
309                          FX_TYPE_COLLECTION,
310                          (PVOID*) &pCollection);
311 
312     pCollection->Lock(&irql);
313     pObject = pCollection->GetItem(Index);
314     pCollection->Unlock(irql);
315 
316     if (pObject == NULL) {
317         return NULL;
318     }
319 
320     return pObject->GetObjectHandle();
321 }
322 
__drv_maxIRQL(DISPATCH_LEVEL)323 __drv_maxIRQL(DISPATCH_LEVEL)
324 WDFOBJECT
325 STDCALL
326 WDFEXPORT(WdfCollectionGetFirstItem)(
327     __in
328     PWDF_DRIVER_GLOBALS DriverGlobals,
329     __in
330     WDFCOLLECTION Collection
331     )
332 {
333     DDI_ENTRY();
334 
335     FxCollection *pCollection;
336     FxObject* pObject;
337     KIRQL irql;
338 
339     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
340                          Collection,
341                          FX_TYPE_COLLECTION,
342                          (PVOID*) &pCollection);
343 
344     pCollection->Lock(&irql);
345     pObject = pCollection->GetFirstItem();
346     pCollection->Unlock(irql);
347 
348     if (pObject != NULL) {
349         return pObject->GetObjectHandle();
350     }
351     else {
352         return NULL;
353     }
354 }
355 
__drv_maxIRQL(DISPATCH_LEVEL)356 __drv_maxIRQL(DISPATCH_LEVEL)
357 WDFOBJECT
358 STDCALL
359 WDFEXPORT(WdfCollectionGetLastItem)(
360     __in
361     PWDF_DRIVER_GLOBALS DriverGlobals,
362     __in
363     WDFCOLLECTION Collection
364     )
365 {
366     DDI_ENTRY();
367 
368     FxCollection *pCollection;
369     FxObject* pObject;
370     KIRQL irql;
371 
372     FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
373                          Collection,
374                          FX_TYPE_COLLECTION,
375                          (PVOID*) &pCollection);
376 
377     pCollection->Lock(&irql);
378     pObject = pCollection->GetLastItem();
379     pCollection->Unlock(irql);
380 
381     if (pObject != NULL) {
382         return pObject->GetObjectHandle();
383     }
384     else {
385         return NULL;
386     }
387 }
388 
389 } // extern "C" of entire file
390