1 /* 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) 7 */ 8 9 // NOTE: Split this file into filter object and device object functions 10 // when the code base grows sufficiently 11 12 /* INCLUDES ******************************************************************/ 13 14 #include "fltmgr.h" 15 #include "fltmgrint.h" 16 17 #define NDEBUG 18 #include <debug.h> 19 20 21 /* DATA *********************************************************************/ 22 23 #define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z) 24 25 // 26 // Pushlock bits 27 // 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) 35 36 /* EXPORTED FUNCTIONS ******************************************************/ 37 38 39 NTSTATUS 40 FLTAPI 41 FltObjectReference(_Inout_ PVOID Object) 42 { 43 if (!FltpExAcquireRundownProtection(&((PFLT_OBJECT)Object)->RundownRef)) 44 { 45 return STATUS_FLT_DELETING_OBJECT; 46 } 47 48 return STATUS_SUCCESS; 49 } 50 51 VOID 52 FLTAPI 53 FltObjectDereference(_Inout_ PVOID Object) 54 { 55 FltpExReleaseRundownProtection(&((PFLT_OBJECT)Object)->RundownRef); 56 } 57 58 59 _Acquires_lock_(_Global_critical_region_) 60 _IRQL_requires_max_(APC_LEVEL) 61 VOID 62 FLTAPI 63 FltAcquirePushLockExclusive(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) 64 { 65 KeEnterCriticalRegion(); 66 67 /* Try acquiring the lock */ 68 if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V)) 69 { 70 /* Someone changed it, use the slow path */ 71 ExfAcquirePushLockExclusive(PushLock); 72 } 73 74 /* Sanity check */ 75 FLT_ASSERT(PushLock->Locked); 76 } 77 78 79 _Acquires_lock_(_Global_critical_region_) 80 _IRQL_requires_max_(APC_LEVEL) 81 VOID 82 FLTAPI 83 FltAcquirePushLockShared(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) 84 { 85 EX_PUSH_LOCK NewValue; 86 87 KeEnterCriticalRegion(); 88 89 /* Try acquiring the lock */ 90 NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC; 91 if (ExpChangePushlock(PushLock, NewValue.Ptr, 0)) 92 { 93 /* Someone changed it, use the slow path */ 94 ExfAcquirePushLockShared(PushLock); 95 } 96 97 /* Sanity checks */ 98 ASSERT(PushLock->Locked); 99 } 100 101 _Releases_lock_(_Global_critical_region_) 102 _IRQL_requires_max_(APC_LEVEL) 103 VOID 104 FLTAPI 105 FltReleasePushLock(_Inout_ _Requires_lock_held_(*_Curr_) _Releases_lock_(*_Curr_) PEX_PUSH_LOCK PushLock) 106 { 107 EX_PUSH_LOCK OldValue = *PushLock; 108 EX_PUSH_LOCK NewValue; 109 110 /* Sanity checks */ 111 FLT_ASSERT(OldValue.Locked); 112 113 /* Check if the pushlock is shared */ 114 if (OldValue.Shared > 1) 115 { 116 /* Decrease the share count */ 117 NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC; 118 } 119 else 120 { 121 /* Clear the pushlock entirely */ 122 NewValue.Value = 0; 123 } 124 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) != 128 OldValue.Ptr)) 129 { 130 /* We have waiters, use the long path */ 131 ExfReleasePushLock(PushLock); 132 } 133 134 KeLeaveCriticalRegion(); 135 } 136 137 _IRQL_requires_max_(PASSIVE_LEVEL) 138 NTSTATUS 139 FLTAPI 140 FltClose(_In_ HANDLE FileHandle) 141 { 142 PAGED_CODE(); 143 144 return ZwClose(FileHandle); 145 } 146 147 _Must_inspect_result_ 148 _IRQL_requires_max_(PASSIVE_LEVEL) 149 NTSTATUS 150 FLTAPI 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, 164 _In_ ULONG EaLength, 165 _In_ ULONG Flags) 166 { 167 UNIMPLEMENTED; 168 return STATUS_NOT_IMPLEMENTED; 169 } 170 171 _Must_inspect_result_ 172 _IRQL_requires_max_(PASSIVE_LEVEL) 173 NTSTATUS 174 FLTAPI 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, 187 _In_ ULONG EaLength, 188 _In_ ULONG Flags) 189 { 190 return FltCreateFileEx(Filter, 191 Instance, 192 FileHandle, 193 NULL, 194 DesiredAccess, 195 ObjectAttributes, 196 IoStatusBlock, 197 AllocationSize, 198 FileAttributes, 199 ShareAccess, 200 CreateDisposition, 201 CreateOptions, 202 EaBuffer, 203 EaLength, 204 Flags); 205 } 206 207 208 209 /* INTERNAL FUNCTIONS ******************************************************/ 210 211 VOID 212 FltpExInitializeRundownProtection(_Out_ PEX_RUNDOWN_REF RundownRef) 213 { 214 ExInitializeRundownProtection(RundownRef); 215 } 216 217 BOOLEAN 218 FltpExAcquireRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef) 219 { 220 return ExAcquireRundownProtection(RundownRef); 221 } 222 223 BOOLEAN 224 FltpExReleaseRundownProtection(_Inout_ PEX_RUNDOWN_REF RundownRef) 225 { 226 ExReleaseRundownProtection(RundownRef); 227 return TRUE; 228 } 229 230 BOOLEAN 231 FltpExRundownCompleted(_Inout_ PEX_RUNDOWN_REF RundownRef) 232 { 233 return _InterlockedExchange((PLONG)RundownRef, 1); 234 } 235 236 NTSTATUS 237 NTAPI 238 FltpObjectRundownWait(_Inout_ PEX_RUNDOWN_REF RundownRef) 239 { 240 //return FltpExWaitForRundownProtectionRelease(RundownRef); 241 return 0; 242 } 243 244 NTSTATUS 245 FltpGetBaseDeviceObjectName(_In_ PDEVICE_OBJECT DeviceObject, 246 _Inout_ PUNICODE_STRING ObjectName) 247 { 248 PDEVICE_OBJECT BaseDeviceObject; 249 NTSTATUS Status; 250 251 /* 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 254 */ 255 BaseDeviceObject = IoGetDeviceAttachmentBaseRef(DeviceObject); 256 Status = FltpGetObjectName(BaseDeviceObject, ObjectName); 257 ObDereferenceObject(BaseDeviceObject); 258 259 return Status; 260 } 261 262 NTSTATUS 263 FltpGetObjectName(_In_ PVOID Object, 264 _Inout_ PUNICODE_STRING ObjectName) 265 { 266 OBJECT_NAME_INFORMATION LocalNameInfo; 267 POBJECT_NAME_INFORMATION ObjectNameInfo = &LocalNameInfo; 268 ULONG ReturnLength; 269 NTSTATUS Status; 270 271 if (ObjectName == NULL) 272 return STATUS_INVALID_PARAMETER; 273 274 /* Get the size of the buffer required to hold the nameinfo */ 275 Status = ObQueryNameString(Object, 276 &LocalNameInfo, 277 sizeof(LocalNameInfo), 278 &ReturnLength); 279 if (Status == STATUS_INFO_LENGTH_MISMATCH) 280 { 281 ObjectNameInfo = ExAllocatePoolWithTag(PagedPool, 282 ReturnLength, 283 FM_TAG_UNICODE_STRING); 284 if (ObjectNameInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES; 285 286 /* Get the actual name info now we have the buffer to hold it */ 287 Status = ObQueryNameString(Object, 288 ObjectNameInfo, 289 ReturnLength, 290 &ReturnLength); 291 } 292 293 294 if (NT_SUCCESS(Status)) 295 { 296 /* Make sure the buffer we were passed is large enough to hold the string */ 297 if (ObjectName->MaximumLength < ObjectNameInfo->Name.Length) 298 { 299 /* It wasn't, let's enlarge the buffer */ 300 Status = FltpReallocateUnicodeString(ObjectName, 301 ObjectNameInfo->Name.Length, 302 FALSE); 303 304 } 305 306 if (NT_SUCCESS(Status)) 307 { 308 /* Copy the object name into the callers buffer */ 309 RtlCopyUnicodeString(ObjectName, &ObjectNameInfo->Name); 310 } 311 } 312 313 if (ObjectNameInfo != &LocalNameInfo) 314 { 315 ExFreePoolWithTag(ObjectNameInfo, FM_TAG_UNICODE_STRING); 316 } 317 318 return Status; 319 } 320 321 ULONG 322 FltpObjectPointerReference(_In_ PFLT_OBJECT Object) 323 { 324 PULONG Result; 325 326 /* Store the old count and increment */ 327 Result = &Object->PointerCount; 328 InterlockedIncrementSizeT(&Object->PointerCount); 329 330 /* Return the initial value */ 331 return *Result; 332 } 333 334 VOID 335 FltpObjectPointerDereference(_In_ PFLT_OBJECT Object) 336 { 337 if (InterlockedDecrementSizeT(&Object->PointerCount) == 0) 338 { 339 // Cleanup 340 FLT_ASSERT(FALSE); 341 } 342 } 343