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

semphore.c

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

Generated on Sat May 15 19:41:45 2004 for test by doxygen 1.3.7