1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel 4 * FILE: ntoskrnl/ex/mutant.c 5 * PURPOSE: Executive Management of Mutants 6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7 * Thomas Weidenmueller 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* DATA **********************************************************************/ 17 18 POBJECT_TYPE ExMutantObjectType = NULL; 19 20 GENERIC_MAPPING ExpMutantMapping = 21 { 22 STANDARD_RIGHTS_READ | MUTANT_QUERY_STATE, 23 STANDARD_RIGHTS_WRITE, 24 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, 25 MUTANT_ALL_ACCESS 26 }; 27 28 static const INFORMATION_CLASS_INFO ExMutantInfoClass[] = 29 { 30 /* MutantBasicInformation */ 31 IQS_SAME(MUTANT_BASIC_INFORMATION, ULONG, ICIF_QUERY), 32 }; 33 34 /* FUNCTIONS *****************************************************************/ 35 36 VOID 37 NTAPI 38 ExpDeleteMutant(PVOID ObjectBody) 39 { 40 DPRINT("ExpDeleteMutant(ObjectBody 0x%p)\n", ObjectBody); 41 42 /* Make sure to release the Mutant */ 43 KeReleaseMutant((PKMUTANT)ObjectBody, 44 MUTANT_INCREMENT, 45 TRUE, 46 FALSE); 47 } 48 49 CODE_SEG("INIT") 50 BOOLEAN 51 NTAPI 52 ExpInitializeMutantImplementation(VOID) 53 { 54 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 55 UNICODE_STRING Name; 56 NTSTATUS Status; 57 DPRINT("Creating Mutant Object Type\n"); 58 59 /* Create the Event Pair Object Type */ 60 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 61 RtlInitUnicodeString(&Name, L"Mutant"); 62 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 63 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT); 64 ObjectTypeInitializer.GenericMapping = ExpMutantMapping; 65 ObjectTypeInitializer.PoolType = NonPagedPool; 66 ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant; 67 ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS; 68 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 69 Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExMutantObjectType); 70 if (!NT_SUCCESS(Status)) return FALSE; 71 return TRUE; 72 } 73 74 /* 75 * @implemented 76 */ 77 NTSTATUS 78 NTAPI 79 NtCreateMutant(OUT PHANDLE MutantHandle, 80 IN ACCESS_MASK DesiredAccess, 81 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 82 IN BOOLEAN InitialOwner) 83 { 84 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 85 HANDLE hMutant; 86 PKMUTANT Mutant; 87 NTSTATUS Status; 88 PAGED_CODE(); 89 DPRINT("NtCreateMutant(0x%p, 0x%x, 0x%p)\n", 90 MutantHandle, DesiredAccess, ObjectAttributes); 91 92 /* Check if we were called from user-mode */ 93 if (PreviousMode != KernelMode) 94 { 95 /* Enter SEH Block */ 96 _SEH2_TRY 97 { 98 /* Check handle pointer */ 99 ProbeForWriteHandle(MutantHandle); 100 } 101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 102 { 103 /* Return the exception code */ 104 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 105 } 106 _SEH2_END; 107 } 108 109 /* Create the Mutant Object*/ 110 Status = ObCreateObject(PreviousMode, 111 ExMutantObjectType, 112 ObjectAttributes, 113 PreviousMode, 114 NULL, 115 sizeof(KMUTANT), 116 0, 117 0, 118 (PVOID*)&Mutant); 119 120 /* Check for success */ 121 if(NT_SUCCESS(Status)) 122 { 123 /* Initialize the Kernel Mutant */ 124 DPRINT("Initializing the Mutant\n"); 125 KeInitializeMutant(Mutant, InitialOwner); 126 127 /* Insert the Object */ 128 Status = ObInsertObject((PVOID)Mutant, 129 NULL, 130 DesiredAccess, 131 0, 132 NULL, 133 &hMutant); 134 135 /* Check for success */ 136 if (NT_SUCCESS(Status)) 137 { 138 /* Enter SEH for return */ 139 _SEH2_TRY 140 { 141 /* Return the handle to the caller */ 142 *MutantHandle = hMutant; 143 } 144 _SEH2_EXCEPT(ExSystemExceptionFilter()) 145 { 146 /* Get the exception code */ 147 Status = _SEH2_GetExceptionCode(); 148 } 149 _SEH2_END; 150 } 151 } 152 153 /* Return Status */ 154 return Status; 155 } 156 157 /* 158 * @implemented 159 */ 160 NTSTATUS 161 NTAPI 162 NtOpenMutant(OUT PHANDLE MutantHandle, 163 IN ACCESS_MASK DesiredAccess, 164 IN POBJECT_ATTRIBUTES ObjectAttributes) 165 { 166 HANDLE hMutant; 167 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 168 NTSTATUS Status; 169 PAGED_CODE(); 170 DPRINT("NtOpenMutant(0x%p, 0x%x, 0x%p)\n", 171 MutantHandle, DesiredAccess, ObjectAttributes); 172 173 /* Check if we were called from user-mode */ 174 if (PreviousMode != KernelMode) 175 { 176 /* Enter SEH Block */ 177 _SEH2_TRY 178 { 179 /* Check handle pointer */ 180 ProbeForWriteHandle(MutantHandle); 181 } 182 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 183 { 184 /* Return the exception code */ 185 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 186 } 187 _SEH2_END; 188 } 189 190 /* Open the Object */ 191 Status = ObOpenObjectByName(ObjectAttributes, 192 ExMutantObjectType, 193 PreviousMode, 194 NULL, 195 DesiredAccess, 196 NULL, 197 &hMutant); 198 199 /* Check for success */ 200 if(NT_SUCCESS(Status)) 201 { 202 /* Enter SEH for return */ 203 _SEH2_TRY 204 { 205 /* Return the handle to the caller */ 206 *MutantHandle = hMutant; 207 } 208 _SEH2_EXCEPT(ExSystemExceptionFilter()) 209 { 210 Status = _SEH2_GetExceptionCode(); 211 } 212 _SEH2_END; 213 } 214 215 /* Return Status */ 216 return Status; 217 } 218 219 /* 220 * @implemented 221 */ 222 NTSTATUS 223 NTAPI 224 NtQueryMutant(IN HANDLE MutantHandle, 225 IN MUTANT_INFORMATION_CLASS MutantInformationClass, 226 OUT PVOID MutantInformation, 227 IN ULONG MutantInformationLength, 228 OUT PULONG ResultLength OPTIONAL) 229 { 230 PKMUTANT Mutant; 231 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 232 NTSTATUS Status; 233 PMUTANT_BASIC_INFORMATION BasicInfo = 234 (PMUTANT_BASIC_INFORMATION)MutantInformation; 235 PAGED_CODE(); 236 237 /* Check buffers and parameters */ 238 Status = DefaultQueryInfoBufferCheck(MutantInformationClass, 239 ExMutantInfoClass, 240 sizeof(ExMutantInfoClass) / 241 sizeof(ExMutantInfoClass[0]), 242 ICIF_PROBE_READ_WRITE, 243 MutantInformation, 244 MutantInformationLength, 245 ResultLength, 246 NULL, 247 PreviousMode); 248 if(!NT_SUCCESS(Status)) 249 { 250 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status); 251 return Status; 252 } 253 254 /* Open the Object */ 255 Status = ObReferenceObjectByHandle(MutantHandle, 256 MUTANT_QUERY_STATE, 257 ExMutantObjectType, 258 PreviousMode, 259 (PVOID*)&Mutant, 260 NULL); 261 /* Check for Status */ 262 if (NT_SUCCESS(Status)) 263 { 264 /* Enter SEH Block for return */ 265 _SEH2_TRY 266 { 267 /* Fill out the Basic Information Requested */ 268 DPRINT("Returning Mutant Information\n"); 269 BasicInfo->CurrentCount = KeReadStateMutant(Mutant); 270 BasicInfo->OwnedByCaller = (Mutant->OwnerThread == 271 KeGetCurrentThread()); 272 BasicInfo->AbandonedState = Mutant->Abandoned; 273 274 /* Return the Result Length if requested */ 275 if (ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION); 276 } 277 _SEH2_EXCEPT(ExSystemExceptionFilter()) 278 { 279 Status = _SEH2_GetExceptionCode(); 280 } 281 _SEH2_END; 282 283 /* Release the Object */ 284 ObDereferenceObject(Mutant); 285 } 286 287 /* Return Status */ 288 return Status; 289 } 290 291 /* 292 * @implemented 293 */ 294 NTSTATUS 295 NTAPI 296 NtReleaseMutant(IN HANDLE MutantHandle, 297 IN PLONG PreviousCount OPTIONAL) 298 { 299 PKMUTANT Mutant; 300 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 301 NTSTATUS Status; 302 PAGED_CODE(); 303 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n", 304 MutantHandle, 305 PreviousCount); 306 307 /* Check if we were called from user-mode */ 308 if ((PreviousCount) && (PreviousMode != KernelMode)) 309 { 310 /* Entry SEH Block */ 311 _SEH2_TRY 312 { 313 /* Make sure the state pointer is valid */ 314 ProbeForWriteLong(PreviousCount); 315 } 316 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 317 { 318 /* Return the exception code */ 319 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 320 } 321 _SEH2_END; 322 } 323 324 /* Open the Object */ 325 Status = ObReferenceObjectByHandle(MutantHandle, 326 0, /* No access rights required */ 327 ExMutantObjectType, 328 PreviousMode, 329 (PVOID*)&Mutant, 330 NULL); 331 332 /* Check for Success and release if such */ 333 if (NT_SUCCESS(Status)) 334 { 335 /* 336 * Release the mutant. doing so might raise an exception which we're 337 * required to catch! 338 */ 339 _SEH2_TRY 340 { 341 /* Release the mutant */ 342 LONG Prev = KeReleaseMutant(Mutant, 343 MUTANT_INCREMENT, 344 FALSE, 345 FALSE); 346 347 /* Return the previous count if requested */ 348 if (PreviousCount) *PreviousCount = Prev; 349 } 350 _SEH2_EXCEPT(ExSystemExceptionFilter()) 351 { 352 /* Get the exception code */ 353 Status = _SEH2_GetExceptionCode(); 354 } 355 _SEH2_END; 356 357 /* Dereference it */ 358 ObDereferenceObject(Mutant); 359 } 360 361 /* Return Status */ 362 return Status; 363 } 364 365 /* EOF */ 366