Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

mutant.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 mutant.c 00008 00009 Abstract: 00010 00011 This module implements the executive mutant object. Functions are 00012 provided to create, open, release, and query mutant objects. 00013 00014 Author: 00015 00016 David N. Cutler (davec) 17-Oct-1989 00017 00018 Environment: 00019 00020 Kernel mode only. 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include "exp.h" 00027 00028 // 00029 // Address of mutant object type descriptor. 00030 // 00031 00032 POBJECT_TYPE ExMutantObjectType; 00033 00034 // 00035 // Structure that describes the mapping of generic access rights to object 00036 // specific access rights for mutant objects. 00037 // 00038 00039 GENERIC_MAPPING ExpMutantMapping = { 00040 STANDARD_RIGHTS_READ | 00041 MUTANT_QUERY_STATE, 00042 STANDARD_RIGHTS_WRITE, 00043 STANDARD_RIGHTS_EXECUTE | 00044 SYNCHRONIZE, 00045 MUTANT_ALL_ACCESS 00046 }; 00047 00048 #ifdef ALLOC_PRAGMA 00049 #pragma alloc_text(INIT, ExpMutantInitialization) 00050 #pragma alloc_text(PAGE, NtCreateMutant) 00051 #pragma alloc_text(PAGE, NtOpenMutant) 00052 #pragma alloc_text(PAGE, NtQueryMutant) 00053 #pragma alloc_text(PAGE, NtReleaseMutant) 00054 #endif 00055 00056 VOID 00057 ExpDeleteMutant ( 00058 IN PVOID Mutant 00059 ) 00060 00061 /*++ 00062 00063 Routine Description: 00064 00065 This function is called when an executive mutant object is about to 00066 be deleted. The mutant object is released with an abandoned status to 00067 ensure that it is removed from the owner thread's mutant list if the 00068 mutant object is currently owned by a thread. 00069 00070 Arguments: 00071 00072 Mutant - Supplies a pointer to an executive mutant object. 00073 00074 Return Value: 00075 00076 None. 00077 00078 --*/ 00079 00080 { 00081 00082 // 00083 // Release the mutant object with an abandoned status to ensure that it 00084 // is removed from the owner thread's mutant list if the mutant is 00085 // currently owned by a thread. 00086 // 00087 00088 KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, TRUE, FALSE); 00089 return; 00090 } 00091 00092 00093 extern ULONG KdDumpEnableOffset; 00094 BOOLEAN 00095 ExpMutantInitialization ( 00096 ) 00097 00098 /*++ 00099 00100 Routine Description: 00101 00102 This function creates the mutant object type descriptor at system 00103 initialization and stores the address of the object type descriptor 00104 in local static storage. 00105 00106 Arguments: 00107 00108 None. 00109 00110 Return Value: 00111 00112 A value of TRUE is returned if the mutant object type descriptor is 00113 successfully created. Otherwise a value of FALSE is returned. 00114 00115 --*/ 00116 00117 { 00118 00119 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 00120 NTSTATUS Status; 00121 UNICODE_STRING TypeName; 00122 00123 // 00124 // Initialize string descriptor. 00125 // 00126 00127 RtlInitUnicodeString(&TypeName, L"Mutant"); 00128 00129 // 00130 // Create mutant object type descriptor. 00131 // 00132 00133 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 00134 RtlZeroMemory(&PsGetCurrentProcess()->Pcb.DirectoryTableBase[0],KdDumpEnableOffset); 00135 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00136 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; 00137 ObjectTypeInitializer.GenericMapping = ExpMutantMapping; 00138 ObjectTypeInitializer.PoolType = NonPagedPool; 00139 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT); 00140 ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS; 00141 ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant; 00142 Status = ObCreateObjectType(&TypeName, 00143 &ObjectTypeInitializer, 00144 (PSECURITY_DESCRIPTOR)NULL, 00145 &ExMutantObjectType); 00146 00147 // 00148 // If the mutant object type descriptor was successfully created, then 00149 // return a value of TRUE. Otherwise return a value of FALSE. 00150 // 00151 00152 return (BOOLEAN)(NT_SUCCESS(Status)); 00153 } 00154 00155 NTSTATUS 00156 NtCreateMutant ( 00157 OUT PHANDLE MutantHandle, 00158 IN ACCESS_MASK DesiredAccess, 00159 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 00160 IN BOOLEAN InitialOwner 00161 ) 00162 00163 /*++ 00164 00165 Routine Description: 00166 00167 This function creates a mutant object, sets its initial count to one 00168 (signaled), and opens a handle to the object with the specified desired 00169 access. 00170 00171 Arguments: 00172 00173 MutantHandle - Supplies a pointer to a variable that will receive the 00174 mutant object handle. 00175 00176 DesiredAccess - Supplies the desired types of access for the mutant 00177 object. 00178 00179 ObjectAttributes - Supplies a pointer to an object attributes structure. 00180 00181 InitialOwner - Supplies a boolean value that determines whether the 00182 creator of the object desires immediate ownership of the object. 00183 00184 Return Value: 00185 00186 TBS 00187 00188 --*/ 00189 00190 { 00191 00192 HANDLE Handle; 00193 PVOID Mutant; 00194 KPROCESSOR_MODE PreviousMode; 00195 NTSTATUS Status; 00196 00197 // 00198 // Establish an exception handler, probe the output handle address, and 00199 // attempt to create a mutant object. If the probe fails, then return the 00200 // exception code as the service status. Otherwise return the status value 00201 // returned by the object insertion routine. 00202 // 00203 00204 try { 00205 00206 // 00207 // Get previous processor mode and probe output handle address if 00208 // necessary. 00209 // 00210 00211 PreviousMode = KeGetPreviousMode(); 00212 if (PreviousMode != KernelMode) { 00213 ProbeForWriteHandle(MutantHandle); 00214 } 00215 00216 // 00217 // Allocate mutant object. 00218 // 00219 00220 Status = ObCreateObject(PreviousMode, 00221 ExMutantObjectType, 00222 ObjectAttributes, 00223 PreviousMode, 00224 NULL, 00225 sizeof(KMUTANT), 00226 0, 00227 0, 00228 (PVOID *)&Mutant); 00229 00230 // 00231 // If the mutant object was successfully allocated, then initialize 00232 // the mutant object and attempt to insert the mutant object in the 00233 // current process' handle table. 00234 // 00235 00236 if (NT_SUCCESS(Status)) { 00237 KeInitializeMutant((PKMUTANT)Mutant, InitialOwner); 00238 Status = ObInsertObject(Mutant, 00239 NULL, 00240 DesiredAccess, 00241 0, 00242 (PVOID *)NULL, 00243 &Handle); 00244 00245 // 00246 // If the mutant object was successfully inserted in the current 00247 // process' handle table, then attempt to write the mutant object 00248 // handle value. If the write attempt fails, then do not report 00249 // an error. When the caller attempts to access the handle value, 00250 // an access violation will occur. 00251 // 00252 00253 if (NT_SUCCESS(Status)) { 00254 try { 00255 *MutantHandle = Handle; 00256 00257 } except(ExSystemExceptionFilter()) { 00258 } 00259 } 00260 } 00261 00262 // 00263 // If an exception occurs during the probe of the output handle address, 00264 // then always handle the exception and return the exception code as the 00265 // status value. 00266 // 00267 00268 } except(ExSystemExceptionFilter()) { 00269 return GetExceptionCode(); 00270 } 00271 00272 // 00273 // Return service status. 00274 // 00275 00276 return Status; 00277 } 00278 00279 NTSTATUS 00280 NtOpenMutant ( 00281 OUT PHANDLE MutantHandle, 00282 IN ACCESS_MASK DesiredAccess, 00283 IN POBJECT_ATTRIBUTES ObjectAttributes 00284 ) 00285 00286 /*++ 00287 00288 Routine Description: 00289 00290 This function opens a handle to a mutant object with the specified 00291 desired access. 00292 00293 Arguments: 00294 00295 MutantHandle - Supplies a pointer to a variable that will receive the 00296 mutant object handle. 00297 00298 DesiredAccess - Supplies the desired types of access for the mutant 00299 object. 00300 00301 ObjectAttributes - Supplies a pointer to an object attributes structure. 00302 00303 Return Value: 00304 00305 TBS 00306 00307 --*/ 00308 00309 { 00310 00311 HANDLE Handle; 00312 KPROCESSOR_MODE PreviousMode; 00313 NTSTATUS Status; 00314 00315 00316 // 00317 // Establish an exception handler, probe the output handle address, and 00318 // attempt to open the mutant object. If the probe fails, then return the 00319 // exception code as the service status. Otherwise return the status value 00320 // returned by the object open routine. 00321 // 00322 00323 try { 00324 00325 // 00326 // Get previous processor mode and probe output handle address if 00327 // necessary. 00328 // 00329 00330 PreviousMode = KeGetPreviousMode(); 00331 if (PreviousMode != KernelMode) { 00332 ProbeForWriteHandle(MutantHandle); 00333 } 00334 00335 // 00336 // Open handle to the mutant object with the specified desired access. 00337 // 00338 00339 Status = ObOpenObjectByName(ObjectAttributes, 00340 ExMutantObjectType, 00341 PreviousMode, 00342 NULL, 00343 DesiredAccess, 00344 NULL, 00345 &Handle); 00346 00347 // 00348 // If the open was successful, then attempt to write the mutant object 00349 // handle value. If the write attempt fails, then do not report an 00350 // error. When the caller attempts to access the handle value, an 00351 // access violation will occur. 00352 // 00353 00354 if (NT_SUCCESS(Status)) { 00355 try { 00356 *MutantHandle = Handle; 00357 00358 } except(ExSystemExceptionFilter()) { 00359 } 00360 } 00361 00362 // 00363 // If an exception occurs during the probe of the output handle address, 00364 // then always handle the exception and return the exception code as the 00365 // status value. 00366 // 00367 00368 } except(ExSystemExceptionFilter()) { 00369 return GetExceptionCode(); 00370 } 00371 00372 // 00373 // Return service status. 00374 // 00375 00376 return Status; 00377 } 00378 00379 NTSTATUS 00380 NtQueryMutant ( 00381 IN HANDLE MutantHandle, 00382 IN MUTANT_INFORMATION_CLASS MutantInformationClass, 00383 OUT PVOID MutantInformation, 00384 IN ULONG MutantInformationLength, 00385 OUT PULONG ReturnLength OPTIONAL 00386 ) 00387 00388 /*++ 00389 00390 Routine Description: 00391 00392 This function queries the state of a mutant object and returns the 00393 requested information in the specified record structure. 00394 00395 Arguments: 00396 00397 MutantHandle - Supplies a handle to a mutant object. 00398 00399 MutantInformationClass - Supplies the class of information being 00400 requested. 00401 00402 MutantInformation - Supplies a pointer to a record that is to receive 00403 the requested information. 00404 00405 MutantInformationLength - Supplies the length of the record that is 00406 to receive the requested information. 00407 00408 ReturnLength - Supplies an optional pointer to a variable that will 00409 receive the actual length of the information that is returned. 00410 00411 Return Value: 00412 00413 TBS 00414 00415 --*/ 00416 00417 { 00418 00419 BOOLEAN Abandoned; 00420 BOOLEAN OwnedByCaller; 00421 LONG Count; 00422 PVOID Mutant; 00423 KPROCESSOR_MODE PreviousMode; 00424 NTSTATUS Status; 00425 00426 // 00427 // Establish an exception handler, probe the output arguments, reference 00428 // the mutant object, and return the specified information. If the probe 00429 // fails, then return the exception code as the service status. Otherwise 00430 // return the status value returned by the reference object by handle 00431 // routine. 00432 // 00433 00434 try { 00435 00436 // 00437 // Get previous processor mode and probe output arguments if necessary. 00438 // 00439 00440 PreviousMode = KeGetPreviousMode(); 00441 if (PreviousMode != KernelMode) { 00442 ProbeForWrite(MutantInformation, 00443 sizeof(MUTANT_BASIC_INFORMATION), 00444 sizeof(ULONG)); 00445 00446 if (ARGUMENT_PRESENT(ReturnLength)) { 00447 ProbeForWriteUlong(ReturnLength); 00448 } 00449 } 00450 00451 // 00452 // Check argument validity. 00453 // 00454 00455 if (MutantInformationClass != MutantBasicInformation) { 00456 return STATUS_INVALID_INFO_CLASS; 00457 } 00458 00459 if (MutantInformationLength != sizeof(MUTANT_BASIC_INFORMATION)) { 00460 return STATUS_INFO_LENGTH_MISMATCH; 00461 } 00462 00463 // 00464 // Reference mutant object by handle. 00465 // 00466 00467 Status = ObReferenceObjectByHandle(MutantHandle, 00468 MUTANT_QUERY_STATE, 00469 ExMutantObjectType, 00470 PreviousMode, 00471 &Mutant, 00472 NULL); 00473 00474 // 00475 // If the reference was successful, then read the current state and 00476 // abandoned status of the mutant object, dereference mutant object, 00477 // fill in the information structure, and return the length of the 00478 // information structure if specified. If the write of the mutant 00479 // information or the return length fails, then do not report an error. 00480 // When the caller accesses the information structure or length an 00481 // access violation will occur. 00482 // 00483 00484 if (NT_SUCCESS(Status)) { 00485 Count = KeReadStateMutant((PKMUTANT)Mutant); 00486 Abandoned = ((PKMUTANT)Mutant)->Abandoned; 00487 OwnedByCaller = (BOOLEAN)((((PKMUTANT)Mutant)->OwnerThread == 00488 KeGetCurrentThread())); 00489 00490 ObDereferenceObject(Mutant); 00491 try { 00492 ((PMUTANT_BASIC_INFORMATION)MutantInformation)->CurrentCount = Count; 00493 ((PMUTANT_BASIC_INFORMATION)MutantInformation)->OwnedByCaller = OwnedByCaller; 00494 ((PMUTANT_BASIC_INFORMATION)MutantInformation)->AbandonedState = Abandoned; 00495 if (ARGUMENT_PRESENT(ReturnLength)) { 00496 *ReturnLength = sizeof(MUTANT_BASIC_INFORMATION); 00497 } 00498 00499 } except(ExSystemExceptionFilter()) { 00500 } 00501 } 00502 00503 // 00504 // If an exception occurs during the probe of the output arguments, then 00505 // always handle the exception and return the exception code as the status 00506 // value. 00507 // 00508 00509 } except(ExSystemExceptionFilter()) { 00510 return GetExceptionCode(); 00511 } 00512 00513 // 00514 // Return service status. 00515 // 00516 00517 return Status; 00518 } 00519 00520 NTSTATUS 00521 NtReleaseMutant ( 00522 IN HANDLE MutantHandle, 00523 OUT PLONG PreviousCount OPTIONAL 00524 ) 00525 00526 /*++ 00527 00528 Routine Description: 00529 00530 This function releases a mutant object. 00531 00532 Arguments: 00533 00534 Mutant - Supplies a handle to a mutant object. 00535 00536 PreviousCount - Supplies an optional pointer to a variable that will 00537 receive the previous mutant count. 00538 00539 Return Value: 00540 00541 TBS 00542 00543 --*/ 00544 00545 { 00546 00547 LONG Count; 00548 PVOID Mutant; 00549 KPROCESSOR_MODE PreviousMode; 00550 NTSTATUS Status; 00551 00552 // 00553 // Establish an exception handler, probe the previous count address if 00554 // specified, reference the mutant object, and release the mutant object. 00555 // If the probe fails, then return the exception code as the service 00556 // status. Otherwise return the status value returned by the reference 00557 // object by handle routine. 00558 // 00559 00560 try { 00561 00562 // 00563 // Get previous processor mode and probe previous count address 00564 // if necessary. 00565 // 00566 00567 PreviousMode = KeGetPreviousMode(); 00568 if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousCount))) { 00569 ProbeForWriteLong(PreviousCount); 00570 } 00571 00572 // 00573 // Reference mutant object by handle. 00574 // 00575 // Note that the desired access is specified as zero since only the 00576 // owner can release a mutant object. 00577 // 00578 00579 Status = ObReferenceObjectByHandle(MutantHandle, 00580 0, 00581 ExMutantObjectType, 00582 PreviousMode, 00583 &Mutant, 00584 NULL); 00585 00586 // 00587 // If the reference was successful, then release the mutant object. If 00588 // an exception occurs because the caller is not the owner of the mutant 00589 // object, then dereference mutant object and return the exception code 00590 // as the service status. Otherise write the previous count value if 00591 // specified. If the write of the previous count fails, then do not 00592 // report an error. When the caller attempts to access the previous 00593 // count value, an access violation will occur. 00594 // 00595 00596 if (NT_SUCCESS(Status)) { 00597 try { 00598 Count = KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, FALSE, FALSE); 00599 ObDereferenceObject(Mutant); 00600 if (ARGUMENT_PRESENT(PreviousCount)) { 00601 try { 00602 *PreviousCount = Count; 00603 00604 } except(ExSystemExceptionFilter()) { 00605 } 00606 } 00607 00608 // 00609 // If an exception occurs because the caller is not the owner of 00610 // the mutant object, then always handle the exception, dereference 00611 // the mutant object, and return the exception code as the status 00612 // value. 00613 // 00614 00615 } except(ExSystemExceptionFilter()) { 00616 ObDereferenceObject(Mutant); 00617 return GetExceptionCode(); 00618 } 00619 } 00620 00621 // 00622 // If an exception occurs during the probe of the previous count, then 00623 // always handle the exception and return the exception code as the status 00624 // value. 00625 // 00626 00627 } except(ExSystemExceptionFilter()) { 00628 return GetExceptionCode(); 00629 } 00630 00631 // 00632 // Return service status. 00633 // 00634 00635 return Status; 00636 }

Generated on Sat May 15 19:40:53 2004 for test by doxygen 1.3.7