2 * PROJECT: Filesystem Filter Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/filters/fltmgr/Object.c
5 * PURPOSE: Miscellaneous library functions
6 * PROGRAMMERS: Ged Murphy (gedmurphy@reactos.org)
9 // NOTE: Split this file into filter object and device object functions
10 // when the code base grows sufficiently
12 /* INCLUDES ******************************************************************/
15 #include "fltmgrint.h"
21 /* DATA *********************************************************************/
23 #define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
28 #define EX_PUSH_LOCK_LOCK_V ((ULONG_PTR)0x0)
29 #define EX_PUSH_LOCK_LOCK ((ULONG_PTR)0x1)
30 #define EX_PUSH_LOCK_WAITING ((ULONG_PTR)0x2)
31 #define EX_PUSH_LOCK_WAKING ((ULONG_PTR)0x4)
32 #define EX_PUSH_LOCK_MULTIPLE_SHARED ((ULONG_PTR)0x8)
33 #define EX_PUSH_LOCK_SHARE_INC ((ULONG_PTR)0x10)
34 #define EX_PUSH_LOCK_PTR_BITS ((ULONG_PTR)0xf)
36 /* EXPORTED FUNCTIONS ******************************************************/
41 FltObjectReference(_Inout_ PVOID Object
)
43 if (!FltpExAcquireRundownProtection(&((PFLT_OBJECT
)Object
)->RundownRef
))
45 return STATUS_FLT_DELETING_OBJECT
;
48 return STATUS_SUCCESS
;
53 FltObjectDereference(_Inout_ PVOID Object
)
55 FltpExReleaseRundownProtection(&((PFLT_OBJECT
)Object
)->RundownRef
);
59 _Acquires_lock_(_Global_critical_region_
)
60 _IRQL_requires_max_(APC_LEVEL
)
63 FltAcquirePushLockExclusive(_Inout_
_Requires_lock_not_held_(*_Curr_
) _Acquires_lock_(*_Curr_
) PEX_PUSH_LOCK PushLock
)
65 KeEnterCriticalRegion();
67 /* Try acquiring the lock */
68 if (InterlockedBitTestAndSet((PLONG
)PushLock
, EX_PUSH_LOCK_LOCK_V
))
70 /* Someone changed it, use the slow path */
71 ExfAcquirePushLockExclusive(PushLock
);
75 FLT_ASSERT(PushLock
->Locked
);
79 _Acquires_lock_(_Global_critical_region_
)
80 _IRQL_requires_max_(APC_LEVEL
)
83 FltAcquirePushLockShared(_Inout_
_Requires_lock_not_held_(*_Curr_
) _Acquires_lock_(*_Curr_
) PEX_PUSH_LOCK PushLock
)
85 EX_PUSH_LOCK NewValue
;
87 KeEnterCriticalRegion();
89 /* Try acquiring the lock */
90 NewValue
.Value
= EX_PUSH_LOCK_LOCK
| EX_PUSH_LOCK_SHARE_INC
;
91 if (ExpChangePushlock(PushLock
, NewValue
.Ptr
, 0))
93 /* Someone changed it, use the slow path */
94 ExfAcquirePushLockShared(PushLock
);
98 ASSERT(PushLock
->Locked
);
101 _Releases_lock_(_Global_critical_region_
)
102 _IRQL_requires_max_(APC_LEVEL
)
105 FltReleasePushLock(_Inout_
_Requires_lock_held_(*_Curr_
) _Releases_lock_(*_Curr_
) PEX_PUSH_LOCK PushLock
)
107 EX_PUSH_LOCK OldValue
= *PushLock
;
108 EX_PUSH_LOCK NewValue
;
111 FLT_ASSERT(OldValue
.Locked
);
113 /* Check if the pushlock is shared */
114 if (OldValue
.Shared
> 1)
116 /* Decrease the share count */
117 NewValue
.Value
= OldValue
.Value
- EX_PUSH_LOCK_SHARE_INC
;
121 /* Clear the pushlock entirely */
125 /* Check if nobody is waiting on us and try clearing the lock here */
126 if ((OldValue
.Waiting
) ||
127 (ExpChangePushlock(PushLock
, NewValue
.Ptr
, OldValue
.Ptr
) !=
130 /* We have waiters, use the long path */
131 ExfReleasePushLock(PushLock
);
134 KeLeaveCriticalRegion();
137 _IRQL_requires_max_(PASSIVE_LEVEL
)
140 FltClose(_In_ HANDLE FileHandle
)
144 return ZwClose(FileHandle
);
147 _Must_inspect_result_
148 _IRQL_requires_max_(PASSIVE_LEVEL
)
151 FltCreateFileEx(_In_ PFLT_FILTER Filter
,
152 _In_opt_ PFLT_INSTANCE Instance
,
153 _Out_ PHANDLE FileHandle
,
154 _Outptr_opt_ PFILE_OBJECT
*FileObject
,
155 _In_ ACCESS_MASK DesiredAccess
,
156 _In_ POBJECT_ATTRIBUTES ObjectAttributes
,
157 _Out_ PIO_STATUS_BLOCK IoStatusBlock
,
158 _In_opt_ PLARGE_INTEGER AllocationSize
,
159 _In_ ULONG FileAttributes
,
160 _In_ ULONG ShareAccess
,
161 _In_ ULONG CreateDisposition
,
162 _In_ ULONG CreateOptions
,
163 _In_reads_bytes_opt_(EaLength
) PVOID EaBuffer
,
168 return STATUS_NOT_IMPLEMENTED
;
173 /* INTERNAL FUNCTIONS ******************************************************/
176 FltpExInitializeRundownProtection(_Out_ PEX_RUNDOWN_REF RundownRef
)
178 ExInitializeRundownProtection(RundownRef
);
182 FltpExAcquireRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef
)
184 return ExAcquireRundownProtection(RundownRef
);
188 FltpExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef
)
190 ExReleaseRundownProtection(RundownRef
);
195 FltpExRundownCompleted(_Inout_ PEX_RUNDOWN_REF RundownRef
)
197 return _InterlockedExchange((PLONG
)RundownRef
, 1);
202 FltpObjectRundownWait(_Inout_ PEX_RUNDOWN_REF RundownRef
)
204 //return FltpExWaitForRundownProtectionRelease(RundownRef);
209 FltpGetBaseDeviceObjectName(_In_ PDEVICE_OBJECT DeviceObject
,
210 _Inout_ PUNICODE_STRING ObjectName
)
212 PDEVICE_OBJECT BaseDeviceObject
;
216 * Get the lowest device object on the stack, which may be the
217 * object we were passed, and lookup the name for that object
219 BaseDeviceObject
= IoGetDeviceAttachmentBaseRef(DeviceObject
);
220 Status
= FltpGetObjectName(BaseDeviceObject
, ObjectName
);
221 ObDereferenceObject(BaseDeviceObject
);
227 FltpGetObjectName(_In_ PVOID Object
,
228 _Inout_ PUNICODE_STRING ObjectName
)
230 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
231 OBJECT_NAME_INFORMATION LocalNameInfo
;
235 if (ObjectName
== NULL
)
236 return STATUS_INVALID_PARAMETER
;
238 /* Get the size of the buffer required to hold the nameinfo */
239 Status
= ObQueryNameString(Object
,
241 sizeof(LocalNameInfo
),
243 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
245 ObjectNameInfo
= ExAllocatePoolWithTag(PagedPool
,
247 FM_TAG_UNICODE_STRING
);
248 if (ObjectNameInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
250 /* Get the actual name info now we have the buffer to hold it */
251 Status
= ObQueryNameString(Object
,
258 if (NT_SUCCESS(Status
))
260 /* Make sure the buffer we were passed is large enough to hold the string */
261 if (ObjectName
->MaximumLength
< ObjectNameInfo
->Name
.Length
)
263 /* It wasn't, let's enlarge the buffer */
264 Status
= FltpReallocateUnicodeString(ObjectName
,
265 ObjectNameInfo
->Name
.Length
,
270 if (NT_SUCCESS(Status
))
272 /* Copy the object name into the callers buffer */
273 RtlCopyUnicodeString(ObjectName
, &ObjectNameInfo
->Name
);
279 ExFreePoolWithTag(ObjectNameInfo
, FM_TAG_UNICODE_STRING
);
286 FltpObjectPointerReference(_In_ PFLT_OBJECT Object
)
290 /* Store the old count and increment */
291 Result
= &Object
->PointerCount
;
292 InterlockedIncrementSizeT(&Object
->PointerCount
);
294 /* Return the initial value */
299 FltpObjectPointerDereference(_In_ PFLT_OBJECT Object
)
301 if (InterlockedDecrementSizeT(&Object
->PointerCount
) == 0)