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
;
171 _Must_inspect_result_
172 _IRQL_requires_max_(PASSIVE_LEVEL
)
175 FltCreateFile(_In_ PFLT_FILTER Filter
,
176 _In_opt_ PFLT_INSTANCE Instance
,
177 _Out_ PHANDLE FileHandle
,
178 _In_ ACCESS_MASK DesiredAccess
,
179 _In_ POBJECT_ATTRIBUTES ObjectAttributes
,
180 _Out_ PIO_STATUS_BLOCK IoStatusBlock
,
181 _In_opt_ PLARGE_INTEGER AllocationSize
,
182 _In_ ULONG FileAttributes
,
183 _In_ ULONG ShareAccess
,
184 _In_ ULONG CreateDisposition
,
185 _In_ ULONG CreateOptions
,
186 _In_reads_bytes_opt_(EaLength
)PVOID EaBuffer
,
190 return FltCreateFileEx(Filter
,
209 /* INTERNAL FUNCTIONS ******************************************************/
212 FltpExInitializeRundownProtection(_Out_ PEX_RUNDOWN_REF RundownRef
)
214 ExInitializeRundownProtection(RundownRef
);
218 FltpExAcquireRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef
)
220 return ExAcquireRundownProtection(RundownRef
);
224 FltpExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef
)
226 ExReleaseRundownProtection(RundownRef
);
231 FltpExRundownCompleted(_Inout_ PEX_RUNDOWN_REF RundownRef
)
233 return _InterlockedExchange((PLONG
)RundownRef
, 1);
238 FltpObjectRundownWait(_Inout_ PEX_RUNDOWN_REF RundownRef
)
240 //return FltpExWaitForRundownProtectionRelease(RundownRef);
245 FltpGetBaseDeviceObjectName(_In_ PDEVICE_OBJECT DeviceObject
,
246 _Inout_ PUNICODE_STRING ObjectName
)
248 PDEVICE_OBJECT BaseDeviceObject
;
252 * Get the lowest device object on the stack, which may be the
253 * object we were passed, and lookup the name for that object
255 BaseDeviceObject
= IoGetDeviceAttachmentBaseRef(DeviceObject
);
256 Status
= FltpGetObjectName(BaseDeviceObject
, ObjectName
);
257 ObDereferenceObject(BaseDeviceObject
);
263 FltpGetObjectName(_In_ PVOID Object
,
264 _Inout_ PUNICODE_STRING ObjectName
)
266 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
267 OBJECT_NAME_INFORMATION LocalNameInfo
;
271 if (ObjectName
== NULL
)
272 return STATUS_INVALID_PARAMETER
;
274 /* Get the size of the buffer required to hold the nameinfo */
275 Status
= ObQueryNameString(Object
,
277 sizeof(LocalNameInfo
),
279 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
281 ObjectNameInfo
= ExAllocatePoolWithTag(PagedPool
,
283 FM_TAG_UNICODE_STRING
);
284 if (ObjectNameInfo
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
286 /* Get the actual name info now we have the buffer to hold it */
287 Status
= ObQueryNameString(Object
,
294 if (NT_SUCCESS(Status
))
296 /* Make sure the buffer we were passed is large enough to hold the string */
297 if (ObjectName
->MaximumLength
< ObjectNameInfo
->Name
.Length
)
299 /* It wasn't, let's enlarge the buffer */
300 Status
= FltpReallocateUnicodeString(ObjectName
,
301 ObjectNameInfo
->Name
.Length
,
306 if (NT_SUCCESS(Status
))
308 /* Copy the object name into the callers buffer */
309 RtlCopyUnicodeString(ObjectName
, &ObjectNameInfo
->Name
);
315 ExFreePoolWithTag(ObjectNameInfo
, FM_TAG_UNICODE_STRING
);
322 FltpObjectPointerReference(_In_ PFLT_OBJECT Object
)
326 /* Store the old count and increment */
327 Result
= &Object
->PointerCount
;
328 InterlockedIncrementSizeT(&Object
->PointerCount
);
330 /* Return the initial value */
335 FltpObjectPointerDereference(_In_ PFLT_OBJECT Object
)
337 if (InterlockedDecrementSizeT(&Object
->PointerCount
) == 0)