Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

642 lines
18 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. mutant.c
  5. Abstract:
  6. This module implements the executive mutant object. Functions are
  7. provided to create, open, release, and query mutant objects.
  8. Author:
  9. David N. Cutler (davec) 17-Oct-1989
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "exp.h"
  15. //
  16. // Address of mutant object type descriptor.
  17. //
  18. POBJECT_TYPE ExMutantObjectType;
  19. //
  20. // Structure that describes the mapping of generic access rights to object
  21. // specific access rights for mutant objects.
  22. //
  23. #ifdef ALLOC_DATA_PRAGMA
  24. #pragma const_seg("INITCONST")
  25. #endif
  26. const GENERIC_MAPPING ExpMutantMapping = {
  27. STANDARD_RIGHTS_READ |
  28. MUTANT_QUERY_STATE,
  29. STANDARD_RIGHTS_WRITE,
  30. STANDARD_RIGHTS_EXECUTE |
  31. SYNCHRONIZE,
  32. MUTANT_ALL_ACCESS
  33. };
  34. #ifdef ALLOC_DATA_PRAGMA
  35. #pragma const_seg()
  36. #endif
  37. #ifdef ALLOC_PRAGMA
  38. #pragma alloc_text(INIT, ExpMutantInitialization)
  39. #pragma alloc_text(PAGE, NtCreateMutant)
  40. #pragma alloc_text(PAGE, NtOpenMutant)
  41. #pragma alloc_text(PAGE, NtQueryMutant)
  42. #pragma alloc_text(PAGE, NtReleaseMutant)
  43. #endif
  44. VOID
  45. ExpDeleteMutant (
  46. IN PVOID Mutant
  47. )
  48. /*++
  49. Routine Description:
  50. This function is called when an executive mutant object is about to
  51. be deleted. The mutant object is released with an abandoned status to
  52. ensure that it is removed from the owner thread's mutant list if the
  53. mutant object is currently owned by a thread.
  54. Arguments:
  55. Mutant - Supplies a pointer to an executive mutant object.
  56. Return Value:
  57. None.
  58. --*/
  59. {
  60. //
  61. // Release the mutant object with an abandoned status to ensure that it
  62. // is removed from the owner thread's mutant list if the mutant is
  63. // currently owned by a thread.
  64. //
  65. KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, TRUE, FALSE);
  66. return;
  67. }
  68. extern ULONG KdDumpEnableOffset;
  69. BOOLEAN
  70. ExpMutantInitialization (
  71. )
  72. /*++
  73. Routine Description:
  74. This function creates the mutant object type descriptor at system
  75. initialization and stores the address of the object type descriptor
  76. in local static storage.
  77. Arguments:
  78. None.
  79. Return Value:
  80. A value of TRUE is returned if the mutant object type descriptor is
  81. successfully created. Otherwise a value of FALSE is returned.
  82. --*/
  83. {
  84. OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
  85. NTSTATUS Status;
  86. UNICODE_STRING TypeName;
  87. //
  88. // Initialize string descriptor.
  89. //
  90. RtlInitUnicodeString(&TypeName, L"Mutant");
  91. //
  92. // Create mutant object type descriptor.
  93. //
  94. RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
  95. RtlZeroMemory(&PsGetCurrentProcess()->Pcb.DirectoryTableBase[0],KdDumpEnableOffset);
  96. ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
  97. ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
  98. ObjectTypeInitializer.GenericMapping = ExpMutantMapping;
  99. ObjectTypeInitializer.PoolType = NonPagedPool;
  100. ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KMUTANT);
  101. ObjectTypeInitializer.ValidAccessMask = MUTANT_ALL_ACCESS;
  102. ObjectTypeInitializer.DeleteProcedure = ExpDeleteMutant;
  103. Status = ObCreateObjectType(&TypeName,
  104. &ObjectTypeInitializer,
  105. (PSECURITY_DESCRIPTOR)NULL,
  106. &ExMutantObjectType);
  107. //
  108. // If the mutant object type descriptor was successfully created, then
  109. // return a value of TRUE. Otherwise return a value of FALSE.
  110. //
  111. return (BOOLEAN)(NT_SUCCESS(Status));
  112. }
  113. NTSTATUS
  114. NtCreateMutant (
  115. OUT PHANDLE MutantHandle,
  116. IN ACCESS_MASK DesiredAccess,
  117. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  118. IN BOOLEAN InitialOwner
  119. )
  120. /*++
  121. Routine Description:
  122. This function creates a mutant object, sets its initial count to one
  123. (signaled), and opens a handle to the object with the specified desired
  124. access.
  125. Arguments:
  126. MutantHandle - Supplies a pointer to a variable that will receive the
  127. mutant object handle.
  128. DesiredAccess - Supplies the desired types of access for the mutant
  129. object.
  130. ObjectAttributes - Supplies a pointer to an object attributes structure.
  131. InitialOwner - Supplies a boolean value that determines whether the
  132. creator of the object desires immediate ownership of the object.
  133. Return Value:
  134. TBS
  135. --*/
  136. {
  137. HANDLE Handle;
  138. PVOID Mutant;
  139. KPROCESSOR_MODE PreviousMode;
  140. NTSTATUS Status;
  141. //
  142. // Establish an exception handler, probe the output handle address, and
  143. // attempt to create a mutant object. If the probe fails, then return the
  144. // exception code as the service status. Otherwise return the status value
  145. // returned by the object insertion routine.
  146. //
  147. try {
  148. //
  149. // Get previous processor mode and probe output handle address if
  150. // necessary.
  151. //
  152. PreviousMode = KeGetPreviousMode();
  153. if (PreviousMode != KernelMode) {
  154. ProbeForWriteHandle(MutantHandle);
  155. }
  156. //
  157. // Allocate mutant object.
  158. //
  159. Status = ObCreateObject(PreviousMode,
  160. ExMutantObjectType,
  161. ObjectAttributes,
  162. PreviousMode,
  163. NULL,
  164. sizeof(KMUTANT),
  165. 0,
  166. 0,
  167. (PVOID *)&Mutant);
  168. //
  169. // If the mutant object was successfully allocated, then initialize
  170. // the mutant object and attempt to insert the mutant object in the
  171. // current process' handle table.
  172. //
  173. if (NT_SUCCESS(Status)) {
  174. KeInitializeMutant((PKMUTANT)Mutant, InitialOwner);
  175. Status = ObInsertObject(Mutant,
  176. NULL,
  177. DesiredAccess,
  178. 0,
  179. (PVOID *)NULL,
  180. &Handle);
  181. //
  182. // If the mutant object was successfully inserted in the current
  183. // process' handle table, then attempt to write the mutant object
  184. // handle value. If the write attempt fails, then do not report
  185. // an error. When the caller attempts to access the handle value,
  186. // an access violation will occur.
  187. //
  188. if (NT_SUCCESS(Status)) {
  189. try {
  190. *MutantHandle = Handle;
  191. } except(ExSystemExceptionFilter()) {
  192. }
  193. }
  194. }
  195. //
  196. // If an exception occurs during the probe of the output handle address,
  197. // then always handle the exception and return the exception code as the
  198. // status value.
  199. //
  200. } except(ExSystemExceptionFilter()) {
  201. return GetExceptionCode();
  202. }
  203. //
  204. // Return service status.
  205. //
  206. return Status;
  207. }
  208. NTSTATUS
  209. NtOpenMutant (
  210. OUT PHANDLE MutantHandle,
  211. IN ACCESS_MASK DesiredAccess,
  212. IN POBJECT_ATTRIBUTES ObjectAttributes
  213. )
  214. /*++
  215. Routine Description:
  216. This function opens a handle to a mutant object with the specified
  217. desired access.
  218. Arguments:
  219. MutantHandle - Supplies a pointer to a variable that will receive the
  220. mutant object handle.
  221. DesiredAccess - Supplies the desired types of access for the mutant
  222. object.
  223. ObjectAttributes - Supplies a pointer to an object attributes structure.
  224. Return Value:
  225. TBS
  226. --*/
  227. {
  228. HANDLE Handle;
  229. KPROCESSOR_MODE PreviousMode;
  230. NTSTATUS Status;
  231. //
  232. // Establish an exception handler, probe the output handle address, and
  233. // attempt to open the mutant object. If the probe fails, then return the
  234. // exception code as the service status. Otherwise return the status value
  235. // returned by the object open routine.
  236. //
  237. try {
  238. //
  239. // Get previous processor mode and probe output handle address if
  240. // necessary.
  241. //
  242. PreviousMode = KeGetPreviousMode();
  243. if (PreviousMode != KernelMode) {
  244. ProbeForWriteHandle(MutantHandle);
  245. }
  246. //
  247. // Open handle to the mutant object with the specified desired access.
  248. //
  249. Status = ObOpenObjectByName(ObjectAttributes,
  250. ExMutantObjectType,
  251. PreviousMode,
  252. NULL,
  253. DesiredAccess,
  254. NULL,
  255. &Handle);
  256. //
  257. // If the open was successful, then attempt to write the mutant object
  258. // handle value. If the write attempt fails, then do not report an
  259. // error. When the caller attempts to access the handle value, an
  260. // access violation will occur.
  261. //
  262. if (NT_SUCCESS(Status)) {
  263. try {
  264. *MutantHandle = Handle;
  265. } except(ExSystemExceptionFilter()) {
  266. }
  267. }
  268. //
  269. // If an exception occurs during the probe of the output handle address,
  270. // then always handle the exception and return the exception code as the
  271. // status value.
  272. //
  273. } except(ExSystemExceptionFilter()) {
  274. return GetExceptionCode();
  275. }
  276. //
  277. // Return service status.
  278. //
  279. return Status;
  280. }
  281. NTSTATUS
  282. NtQueryMutant (
  283. IN HANDLE MutantHandle,
  284. IN MUTANT_INFORMATION_CLASS MutantInformationClass,
  285. OUT PVOID MutantInformation,
  286. IN ULONG MutantInformationLength,
  287. OUT PULONG ReturnLength OPTIONAL
  288. )
  289. /*++
  290. Routine Description:
  291. This function queries the state of a mutant object and returns the
  292. requested information in the specified record structure.
  293. Arguments:
  294. MutantHandle - Supplies a handle to a mutant object.
  295. MutantInformationClass - Supplies the class of information being
  296. requested.
  297. MutantInformation - Supplies a pointer to a record that is to receive
  298. the requested information.
  299. MutantInformationLength - Supplies the length of the record that is
  300. to receive the requested information.
  301. ReturnLength - Supplies an optional pointer to a variable that will
  302. receive the actual length of the information that is returned.
  303. Return Value:
  304. TBS
  305. --*/
  306. {
  307. BOOLEAN Abandoned;
  308. BOOLEAN OwnedByCaller;
  309. LONG Count;
  310. PVOID Mutant;
  311. KPROCESSOR_MODE PreviousMode;
  312. NTSTATUS Status;
  313. //
  314. // Establish an exception handler, probe the output arguments, reference
  315. // the mutant object, and return the specified information. If the probe
  316. // fails, then return the exception code as the service status. Otherwise
  317. // return the status value returned by the reference object by handle
  318. // routine.
  319. //
  320. try {
  321. //
  322. // Get previous processor mode and probe output arguments if necessary.
  323. //
  324. PreviousMode = KeGetPreviousMode();
  325. if (PreviousMode != KernelMode) {
  326. ProbeForWriteSmallStructure(MutantInformation,
  327. sizeof(MUTANT_BASIC_INFORMATION),
  328. sizeof(ULONG));
  329. if (ARGUMENT_PRESENT(ReturnLength)) {
  330. ProbeForWriteUlong(ReturnLength);
  331. }
  332. }
  333. //
  334. // Check argument validity.
  335. //
  336. if (MutantInformationClass != MutantBasicInformation) {
  337. return STATUS_INVALID_INFO_CLASS;
  338. }
  339. if (MutantInformationLength != sizeof(MUTANT_BASIC_INFORMATION)) {
  340. return STATUS_INFO_LENGTH_MISMATCH;
  341. }
  342. //
  343. // Reference mutant object by handle.
  344. //
  345. Status = ObReferenceObjectByHandle(MutantHandle,
  346. MUTANT_QUERY_STATE,
  347. ExMutantObjectType,
  348. PreviousMode,
  349. &Mutant,
  350. NULL);
  351. //
  352. // If the reference was successful, then read the current state and
  353. // abandoned status of the mutant object, dereference mutant object,
  354. // fill in the information structure, and return the length of the
  355. // information structure if specified. If the write of the mutant
  356. // information or the return length fails, then do not report an error.
  357. // When the caller accesses the information structure or length an
  358. // access violation will occur.
  359. //
  360. if (NT_SUCCESS(Status)) {
  361. Count = KeReadStateMutant((PKMUTANT)Mutant);
  362. Abandoned = ((PKMUTANT)Mutant)->Abandoned;
  363. OwnedByCaller = (BOOLEAN)((((PKMUTANT)Mutant)->OwnerThread ==
  364. KeGetCurrentThread()));
  365. ObDereferenceObject(Mutant);
  366. try {
  367. ((PMUTANT_BASIC_INFORMATION)MutantInformation)->CurrentCount = Count;
  368. ((PMUTANT_BASIC_INFORMATION)MutantInformation)->OwnedByCaller = OwnedByCaller;
  369. ((PMUTANT_BASIC_INFORMATION)MutantInformation)->AbandonedState = Abandoned;
  370. if (ARGUMENT_PRESENT(ReturnLength)) {
  371. *ReturnLength = sizeof(MUTANT_BASIC_INFORMATION);
  372. }
  373. } except(ExSystemExceptionFilter()) {
  374. }
  375. }
  376. //
  377. // If an exception occurs during the probe of the output arguments, then
  378. // always handle the exception and return the exception code as the status
  379. // value.
  380. //
  381. } except(ExSystemExceptionFilter()) {
  382. return GetExceptionCode();
  383. }
  384. //
  385. // Return service status.
  386. //
  387. return Status;
  388. }
  389. NTSTATUS
  390. NtReleaseMutant (
  391. IN HANDLE MutantHandle,
  392. OUT PLONG PreviousCount OPTIONAL
  393. )
  394. /*++
  395. Routine Description:
  396. This function releases a mutant object.
  397. Arguments:
  398. Mutant - Supplies a handle to a mutant object.
  399. PreviousCount - Supplies an optional pointer to a variable that will
  400. receive the previous mutant count.
  401. Return Value:
  402. TBS
  403. --*/
  404. {
  405. LONG Count;
  406. PVOID Mutant;
  407. KPROCESSOR_MODE PreviousMode;
  408. NTSTATUS Status;
  409. //
  410. // Establish an exception handler, probe the previous count address if
  411. // specified, reference the mutant object, and release the mutant object.
  412. // If the probe fails, then return the exception code as the service
  413. // status. Otherwise return the status value returned by the reference
  414. // object by handle routine.
  415. //
  416. try {
  417. //
  418. // Get previous processor mode and probe previous count address
  419. // if necessary.
  420. //
  421. PreviousMode = KeGetPreviousMode();
  422. if ((PreviousMode != KernelMode) && (ARGUMENT_PRESENT(PreviousCount))) {
  423. ProbeForWriteLong(PreviousCount);
  424. }
  425. //
  426. // Reference mutant object by handle.
  427. //
  428. // Note that the desired access is specified as zero since only the
  429. // owner can release a mutant object.
  430. //
  431. Status = ObReferenceObjectByHandle(MutantHandle,
  432. 0,
  433. ExMutantObjectType,
  434. PreviousMode,
  435. &Mutant,
  436. NULL);
  437. //
  438. // If the reference was successful, then release the mutant object. If
  439. // an exception occurs because the caller is not the owner of the mutant
  440. // object, then dereference mutant object and return the exception code
  441. // as the service status. Otherise write the previous count value if
  442. // specified. If the write of the previous count fails, then do not
  443. // report an error. When the caller attempts to access the previous
  444. // count value, an access violation will occur.
  445. //
  446. if (NT_SUCCESS(Status)) {
  447. try {
  448. PERFINFO_DECLARE_OBJECT(Mutant);
  449. Count = KeReleaseMutant((PKMUTANT)Mutant, MUTANT_INCREMENT, FALSE, FALSE);
  450. ObDereferenceObject(Mutant);
  451. if (ARGUMENT_PRESENT(PreviousCount)) {
  452. try {
  453. *PreviousCount = Count;
  454. } except(ExSystemExceptionFilter()) {
  455. }
  456. }
  457. //
  458. // If an exception occurs because the caller is not the owner of
  459. // the mutant object, then always handle the exception, dereference
  460. // the mutant object, and return the exception code as the status
  461. // value.
  462. //
  463. } except(ExSystemExceptionFilter()) {
  464. ObDereferenceObject(Mutant);
  465. return GetExceptionCode();
  466. }
  467. }
  468. //
  469. // If an exception occurs during the probe of the previous count, then
  470. // always handle the exception and return the exception code as the status
  471. // value.
  472. //
  473. } except(ExSystemExceptionFilter()) {
  474. return GetExceptionCode();
  475. }
  476. //
  477. // Return service status.
  478. //
  479. return Status;
  480. }