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 ICI_SQ_SAME( sizeof(MUTANT_BASIC_INFORMATION), sizeof(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 MutantInformation, 243 MutantInformationLength, 244 ResultLength, 245 NULL, 246 PreviousMode); 247 if(!NT_SUCCESS(Status)) 248 { 249 DPRINT("NtQueryMutant() failed, Status: 0x%x\n", Status); 250 return Status; 251 } 252 253 /* Open the Object */ 254 Status = ObReferenceObjectByHandle(MutantHandle, 255 MUTANT_QUERY_STATE, 256 ExMutantObjectType, 257 PreviousMode, 258 (PVOID*)&Mutant, 259 NULL); 260 /* Check for Status */ 261 if (NT_SUCCESS(Status)) 262 { 263 /* Enter SEH Block for return */ 264 _SEH2_TRY 265 { 266 /* Fill out the Basic Information Requested */ 267 DPRINT("Returning Mutant Information\n"); 268 BasicInfo->CurrentCount = KeReadStateMutant(Mutant); 269 BasicInfo->OwnedByCaller = (Mutant->OwnerThread == 270 KeGetCurrentThread()); 271 BasicInfo->AbandonedState = Mutant->Abandoned; 272 273 /* Return the Result Length if requested */ 274 if (ResultLength) *ResultLength = sizeof(MUTANT_BASIC_INFORMATION); 275 } 276 _SEH2_EXCEPT(ExSystemExceptionFilter()) 277 { 278 Status = _SEH2_GetExceptionCode(); 279 } 280 _SEH2_END; 281 282 /* Release the Object */ 283 ObDereferenceObject(Mutant); 284 } 285 286 /* Return Status */ 287 return Status; 288 } 289 290 /* 291 * @implemented 292 */ 293 NTSTATUS 294 NTAPI 295 NtReleaseMutant(IN HANDLE MutantHandle, 296 IN PLONG PreviousCount OPTIONAL) 297 { 298 PKMUTANT Mutant; 299 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 300 NTSTATUS Status; 301 PAGED_CODE(); 302 DPRINT("NtReleaseMutant(MutantHandle 0x%p PreviousCount 0x%p)\n", 303 MutantHandle, 304 PreviousCount); 305 306 /* Check if we were called from user-mode */ 307 if ((PreviousCount) && (PreviousMode != KernelMode)) 308 { 309 /* Entry SEH Block */ 310 _SEH2_TRY 311 { 312 /* Make sure the state pointer is valid */ 313 ProbeForWriteLong(PreviousCount); 314 } 315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 316 { 317 /* Return the exception code */ 318 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 319 } 320 _SEH2_END; 321 } 322 323 /* Open the Object */ 324 Status = ObReferenceObjectByHandle(MutantHandle, 325 0, /* No access rights required */ 326 ExMutantObjectType, 327 PreviousMode, 328 (PVOID*)&Mutant, 329 NULL); 330 331 /* Check for Success and release if such */ 332 if (NT_SUCCESS(Status)) 333 { 334 /* 335 * Release the mutant. doing so might raise an exception which we're 336 * required to catch! 337 */ 338 _SEH2_TRY 339 { 340 /* Release the mutant */ 341 LONG Prev = KeReleaseMutant(Mutant, 342 MUTANT_INCREMENT, 343 FALSE, 344 FALSE); 345 346 /* Return the previous count if requested */ 347 if (PreviousCount) *PreviousCount = Prev; 348 } 349 _SEH2_EXCEPT(ExSystemExceptionFilter()) 350 { 351 /* Get the exception code */ 352 Status = _SEH2_GetExceptionCode(); 353 } 354 _SEH2_END; 355 356 /* Dereference it */ 357 ObDereferenceObject(Mutant); 358 } 359 360 /* Return Status */ 361 return Status; 362 } 363 364 /* EOF */ 365